本文是基于80C51所作的交通灯显示系统,为本人单片机课程设计,内容如下:

  1. 东西方向、南北方向均有红、黄、绿三种信号灯;
  2. 带紧急制动按钮,按钮按下,所有方向亮红灯;再次按下,恢复正常显示;
  3. 夜间模式按钮按下,所有方向显示黄灯闪烁;
  4. 实时提醒绿灯亮的剩余时间(用两位数码管显示,使用共阳极数码管)。

🚦基于C51单片机的交通灯显示系统仓库(Github)
😉本人Github

Traffic-Light-Display-System-Based-on-C51

本项目为本人课程设计备份(基于C51单片机的交通灯显示系统)

交通灯功能特点

为对十字路口交通进行合理而有效的控制,本设计的数显交通灯系统需具备以下几种功能:

  1. 在十字路口进行控制时,能够实现红、绿、黄3种颜色信号灯的颜色切换显示,以此来提示汽车进行直道通行、停止通行或转弯;
  2. 两干道交替允许通行,每次放行30秒,黄灯亮5秒;
  3. 当按下紧急制动按钮后,对系统进行中断,东西南北均显示红灯,再次按下时恢复正常状态;
  4. 当按下夜间模式按钮后,对系统进行中断,所有方向均闪烁黄灯;
  5. 将倒计时使用两位共阳极七段数码管进行时间显示,对直道通行、停止通行或转弯时间进行倒计时显示,提示各路口汽车通行时间。

设计思路

为实现上文列出的十字路口交通控制三项基本功能,系统采用AT89C51单片机作为交通灯控制设计的核心模块,使用16位计时器进行倒计时、共阳极数码管进行倒计时显示、红黄绿三种颜色的LED作为交通灯、利用外部中断0来进入紧急模式及夜间模式。在系统设计的过程中,需要对系统进行硬件和软件两个方面的设计,设计完成后,为使人工管理控制更加方便快捷,还需对设计好的系统进行仿真,以便于程序的调整管控。

Proteus仿真

为了更直观看到交通灯工作过程,本项目采用了Proteus软件进行模拟仿真,通过调试仿真结果基本能满足使用要求,可以根据实际需要调整不同方向灯亮的时间。

keil 5的应用

与大多数集成开发环境类似,Keil 5集成开发环境也是用工程的方法来管理文件,在一个工程文件中源程序(C51程序、汇编程序)、头文件等都可以进行统一管理。
安装运行KEIL 5,使用KEIL的开发工具进行项目开发过程,与其他软件开发项目的过程基本上相同:

  1. 创建C 语言或汇编语言的源程序。
  2. 编译或汇编源文件。
  3. 纠正源文件中的错误。
  4. 从编译器和汇编器连接目标文件。
  5. 测试连接的应用程序。

程序代码(C语言)

#include <reg51.h>

sbit Red_nb=P2^6;		                //南北红灯标志
sbit Yellow_nb=P2^5;	                //南北黄灯标志
sbit Green_nb=P2^4;                     //南北绿灯标志

sbit Red_dx=P2^3;		                //东西红灯标志
sbit Yellow_dx=P2^2;	                //东西黄灯标志
sbit Green_dx=P2^1;		                //东西绿灯标志

bit dx_nb=0;			                //东西南北控制位
bit Yellow_status=0;	                //黄灯闪烁标志位

unsigned char  sec_dx;  		    	//东西方向时间存储变量
unsigned char  sec_nb;			    	//南北方向时间存储变量
float  set_timedx=30;			    	//东西方向的通行单次时间
float  set_timenb=30;				    //南北方向的通行单次时间
unsigned char  buf[4];				    //秒显示的变量
unsigned char data countt0;             //定时器0中断计数器
unsigned char data countt1;             //定时器1中断计数器

unsigned char flag_option=0;            //功能选择位:1 紧急模式;2 夜间模式

sbit  key_EP=P3^2;		                //紧急模式
unsigned char conut_ER;                 //紧急状态

sbit  key_night=P3^3;		            //夜间模式
unsigned char flag_Night;		        //夜间状态
unsigned char conut_night;              //夜间模式

unsigned char code led[11]={	        //共阴极字型码
    0x3f,  //--0
    0x06,  //--1
    0x5b,  //--2
    0x4f,  //--3
    0x66,  //--4
    0x6d,  //--5
    0x7d,  //--6
    0x07,  //--7
    0x7f,  //--8
    0x6f,  //--9
    0x00   //--NULL
};



/*延时函数*/
void delay(int time)
{
    unsigned int j,k;
    for(j=0;j<time;j++)			
       for(k=0;k<124;k++);		
}

/*显示函数*/
void display(void)
{
    buf[0]=sec_nb/10; 		//第1位 东西十位
    buf[1]=sec_nb%10; 		//第2位 东西个位
    buf[2]=sec_dx/10; 		//第3位 南北十位
    buf[3]=sec_dx%10; 		//第4位 南北个位
    P1=~0xfe;           		//LED1
    P0=~led[buf[0]];		    //东西十位
    delay(1);
    P1=~0xfd;             	//LED2
    P0=~led[buf[1]];		    //东西个位
    delay(1);				
    P1=~0Xfb;		  		//LED3
    P0=~led[buf[2]];		    //南北十位
    delay(1);				
    P1=~0Xf7;				//LED4
    P0=~led[buf[3]];		    //南北个位
    delay(1);				
}

/*功能函数*/
void function(void)
{
    switch (flag_option)
    {
        case 1:
        {
            conut_ER=1-conut_ER;
            if(conut_ER==1)
            {
                TR0=0;						//关交通灯定时器
                P2=0x00;					//关全部信号灯
                Red_dx=1;                   //全部置红灯
                Red_nb=1;
            }		
            if(conut_ER==0)
            {
                TR0=1;						//开交通灯定时器
                P2=0X00;					//关全部信号灯
                Green_dx=1;					//东西绿灯亮
                Red_nb=1;					//南北红灯亮
                sec_dx=set_timedx;          //回到初值
                sec_nb=sec_dx+5;
            }	
            flag_option=0;	
            break;
        }
        case 2:
        {
            conut_night=1-conut_night;
            if(conut_night==1)
            {
                TR0=0;						//关交通灯定时器
                P2=0x00;                    //关全部信号灯
                flag_Night=1;               //打开夜间模式
                sec_dx=00;					//四个方向的时间都为00
                sec_nb=00;
            }
            if(conut_night==0)
            {
                TR0=1;						//开交通灯定时器
                P2=0x00;                    //关全部信号灯
                Green_dx=1;					//东西绿灯亮
                Red_nb=1;					//南北红灯亮
                flag_Night=0;               //打开夜间模式
                sec_dx=set_timedx;          //回到初值
                sec_nb=sec_dx+5;
            }
            flag_option=0;
            break;
        }
        default:
            break;
    }
}

/*处理整个交通灯计时*/
void time0(void) interrupt 1 using 1  	//定时中断子程序
{
    TH0=0x4C;							//重赋初值;11.0592m晶振50ms
    TL0=0X00;
    TR0=1;								//开交通灯定时器
    countt0++;							//计数器数加1(用于计算时间)
    if(countt0==20)	                  	//定时器中断次数=20时(即1秒时)
    {	
        countt0=0;						//清零计数器
        sec_dx--;						//东西时间减1
        sec_nb--;						//南北时间减1
        if(sec_nb==0&&sec_dx==5&&(Yellow_status==0))		//当南北倒计时到0时,重置5秒,用于黄灯闪烁时间
        {
            sec_nb=5;
            Yellow_status=1;
        }
        if(sec_dx==0&&sec_nb==5&&(Yellow_status==0)) 		//当东西倒计时到0时,重置5秒,用于黄灯闪烁时间
        {
            sec_dx=5;
            Yellow_status=1;			//启动黄灯开始倒计时
        }
        if((sec_nb<=5)&&(dx_nb==0)&&(Yellow_status==1))  		//东西黄灯闪
        {
            Green_dx=0;
            Yellow_dx=~Yellow_dx;
        }
        if((sec_dx<=5)&&(dx_nb==1)&&(Yellow_status==1))  		//南北黄灯闪
        {
            Green_nb=0;
            Yellow_nb=~Yellow_nb;
        }
        if(dx_nb==0&&sec_nb==0&&sec_dx==0)			            //东西通行:当黄灯时间、通行方向倒计时到0时
        {
            P2=0x00;					//重置东西南背方向的红绿灯
            Green_nb=1;					//南北绿灯亮
            Red_dx=1;					//东西红灯亮
            dx_nb=!dx_nb;				//交换通行方向
            Yellow_status=0;			//关闭黄灯闪烁
            sec_dx=set_timedx+5;			//重赋东西方向的起始值
            sec_nb=set_timenb;		//重赋南北方向的起始值
        }
        if(dx_nb==1&&sec_dx==0&&sec_nb==0)			            //南北通行:当黄灯时间、通行方向倒计时到0时
        {
            P2=0X00;					//重置东西南北的红绿灯状态
            Green_dx=1;					//东西绿灯亮
            Red_nb=1;					//南北红灯亮
            dx_nb=!dx_nb;				//交换通行方向
            Yellow_status=0;					//关闭黄灯闪烁
            sec_dx=set_timedx;		//重赋东西方向的起始值
            sec_nb=set_timenb+5;			//重赋南北方向的起始值
        }
    }
}

/*用来处理夜间黄灯闪烁*/
void time1(void) interrupt 3 			//定时中断子程序
{
    TH1=0x4C;							//重赋初值;11.0592m晶振50ms
    TL1=0X00;
    countt1++;							//计数器数加1(用于计算时间)
    if(countt1==10)					    //定时器中断次数=10时(即0.5秒)
	{	   
		if(flag_Night==1)
	    {
			Yellow_nb=~Yellow_nb;		//南北黄灯
			Yellow_dx=~Yellow_nb;		//东西黄灯   
		}	
	} 
    if(countt1==20)	                  	//定时器中断次数=20时(即1秒时)
    {
        countt1=0;						//清零计数器
        if(flag_Night==1)
        {
            Yellow_nb=~Yellow_nb;		//南北黄灯
            Yellow_dx=~Yellow_nb;		//东西黄灯
        }
    }
}


//外部中断0
void int0(void) interrupt 0 using 1	    //紧急模式
{
    while(!key_EP)display();
    flag_option=1;
}

//外部中断1
void int1(void) interrupt 2 using 1	    //夜间模式
{
    while(!key_night)display();
    flag_option=2;
}

/*初始化函数*/
void init()
{
    TMOD=0X11;	   						//定时器设置
    TH1=0x4C;							//TH1重赋初值;11.0592m晶振50ms
    TL1=0X00;
    TH0=0x4C;							//TH0重赋初值;11.0592m晶振50ms
    TL0=0X00;
    TCON=0X50;							//启动定时0、定时1
    IE=0x8F;							//开总中断;定时器1中断开启;开外部中断1;定时器0中断开启;开外部中断
    P2=0Xc3;							//开始默认状态,东西绿灯,南北黄灯
    sec_nb=35;							//南北方向初始时间
    sec_dx=30;							//东西方向初始时间
}

//主程序
void main()
{
    init();								//初始化定时器、中断服务
    while(1)					 		
    {
        if(flag_option!=0)function(); 	//调用功能函数
        display(); 						//调用显示函数
    }
}