基于51单片机的交通灯控制系统:东西方向通行、南北方向通行、按键启动

基于51单片机交通灯控制器

管制+启动+黄灯闪烁

仿真:proteus 7.8

程序编译器:keil 4/keil 5

编程语言:C语言

设计编号:J012

目录标题

  • 基于51单片机交通灯控制器
  • 功能说明
  • 仿真图
  • 正常运行模式
  • 南北方向通行
  • 东西方向通行
  • 程序设计
  • 倒计时的产生
  • 红黄绿灯状态处理
  • 倒计时显示处理
  • 按键处理
  • 资料清单
  • 功能说明

    LED灯的定时控制;数码管的显示及闪烁;独立按键的读取与判断;定时器的设置与应用。
    单片机控制东西、南北这两组交通灯LED,同时在数码管上显示剩余时间,当剩余时间少于5s时,数码管以每秒2次的速度闪亮,黄灯闪烁5s。

    1. 当“暂停”按键按下时,交通灯暂停变化,再次按下就继续变化;
    2. 当东西键按下时,东西方向灯全绿,南北方向全红;
    3. 当南北键按下时,南北方向灯全绿,东西方向全红;
    4. 具体秒数可在程序改数字实现。

    仿真图

    正常运行模式

    img

    南北方向通行

    当南北键按下时,南北方向灯全绿,东西方向全红;

    img

    东西方向通行

    当东西键按下时,东西方向灯全绿,南北方向全红;

    img

    程序设计

    img

    程序讲解

    主要的核心点是倒计时,和LED灯亮灭控制

    倒计时的产生

    记住这个点就可以设计软件了。首先要有时间基础,倒计时从哪来呢?

    一般两个来源:

    1,延时

    delay(1000ms);
    

    通过死循环卡主软件的运行来达到延时效果,程序执行效率极低,不可取。

    2,定时

    通过定时器产生时基。软件设置50ms产生一次定时中断,在中断执行函数中做计数。

    	TMOD |=0X01;
    	TH0=0X4C;
    	TL0=0X00;
    	ET0=1;
    	TR0=1;//打开定时器中断
    

    20ms执行一次中断函数,通过count1s累加到50判断时间过去了一秒。设置一秒标志位all_mode_flag1s置一。

    	void Timer0() interrupt 1
    {
    	TH0=0XBB;
    	TL0=0X00;
    	KeyScan();
     	
    	if(++count500ms<12){
    	
    	}else{
    	  count500ms = 0;
    		if(FilteFlag){//闪烁标志位
    			FilteFlag = 0;
    		}else{
    			FilteFlag =1;
    		}
    	} 
    
    	if(++count1s<50)	return;
    	count1s=0;
    	if(StaSysterm==NormalRun) flag1s=1;	 //非正常运行时,不红绿灯数值不减一	
    	all_mode_flag1s =1;
    }
    

    在主函数while循环里判断标志位,如果是1,则倒计时计数值减一,即完成了倒计时的软件设计思路

    LEDScan();				  		
    //数码管即LED扫描
    KeyDriver();			  		
    //键盘驱动扫描
    if(flag1s)//1S执行一次
    {
        flag1s=0;
        NS_time--;			  		
        //红绿灯倒计时时间减
        WE_time--;
    }	
    

    红黄绿灯状态处理

    正常红绿灯运行分有四个模式

    1.东西方向绿灯通行,南北方向红灯

    2.东西方向黄灯通行,南北方向红灯

    3.南北方向绿灯通行,东西方向红灯

    4.南北方向黄灯通行,东西方向红灯

    5.执行第一步

    image-20220904173413785

       if(StaSysterm==NormalRun)	//状态切换
        {
       	if(NS_time==0 || WE_time==0)//当东西或者南北方向通行时间倒数到0,切换状态
       	{
       		switch(index)				 //改变红绿灯的状态,状态机
       		{
       			case 0:
       			{
       				index=1;
       				NS_time=main_green_straight_cnt;//南北方向绿灯通行时间
       				WE_time=main_green_straight_cnt+yellow_cnt;//东西红灯方向通行时间       注意!红灯时间要长一点
       				P2=0X09;	//需要亮的灯转换为二进制位0000 1001,对应P2口的P2^0和P2^3,
       				          //对应仿真图的绿灯L0和红灯L3亮。
    
       			}break;
       			case 1:
       			{
       				index=2;
       				NS_time = yellow_cnt;
       				P2=0X0A;
    
       			}break;
       			case 2:
       			{
       				index=3;
       				NS_time=sec_green_straight_cnt+yellow_cnt;//南北方向红灯时间 
       				WE_time=sec_green_straight_cnt;//东西方向绿灯时间 
       				P2=0X24;	
    
       			}break;
       			case 3:
       			{
       				index=0;
       				WE_time=yellow_cnt;
       				P2=0X14;
    
       			}break;
       			default:break;
       		}
       	}
    

    倒计时显示处理

    实际上倒计时显示就是显示NS_time–; WE_time–;设计函数通过数码管分别显示A方向的NS_time和B方向的WE_time即可

    					Seg_Display(NS_time/10,0);
    Seg_Display(NS_time%10,1);
    Seg_Display(WE_time/10,2);
    Seg_Display(WE_time%10,3);
    

    按键处理

    
    void KeyScan()						        	//键盘扫描
    {
    	static uchar keybuf[3]={0XFF,0XFF,0XFF};
    	uchar i;
    	keybuf[0]=(keybuf[0]<<1)|KEY1;
    	keybuf[1]=(keybuf[1]<<1)|KEY2;
    	keybuf[2]=(keybuf[2]<<1)|KEY3;
    
    	for(i=0;i<3;i++)
    	{
    		if(keybuf[i]==0X00)			keystr[i]=0;
    		else if(keybuf[i]==0XFF) 	keystr[i]=1;
    	}
    }
    void KeyAction(uchar key)					 	//键盘执行
    {
    	switch(key)
    	{
    		case 0:	
    			if(StaSysterm == NormalRun){
    				StaSysterm=Stop;
    				LedState = P2;
    			}else if(StaSysterm == Stop){
    				StaSysterm = NormalRun;
    				P2 = LedState;
    			}
    
    			break;	
    		
    		case 1:	
    			if(StaSysterm == NormalRun){
    				StaSysterm=NSRun;
    				LedState = P2;
    			}else if(StaSysterm == NSRun){
    				StaSysterm = NormalRun;
    				P2 = LedState;
    			}
    
    			break;
    		
    		case 2:	
    			if(StaSysterm==NormalRun){
    				StaSysterm=WERun;
    				LedState = P2;
    			}else if(StaSysterm==WERun){
    				StaSysterm = NormalRun;
    				P2 = LedState;
    			}
    
    			break;
    			
    			  default:break;
    	}
    }
    void KeyDriver()								 //键盘驱动
    {
    	uchar i;
    	for(i=0;i<3;i++)
    	{
    		if(keystr[i]!=backup[i])
    		{
    			if(keystr[i]==0)
    				KeyAction(i);//这里适当修改程序可以实现组合按键的效果
    		}
    		backup[i]=keystr[i];
    	}
    }
    

    资料清单

    资料下载

    img

    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于51单片机的交通灯控制系统:东西方向通行、南北方向通行、按键启动

    发表评论