实现功能:
- 十字路口交通灯控制器的设计LED发光二极管模拟东、西、方向的交通灯LED点阵显示屏显示两个方向的剩余时间,用按钮控制显示状态。时间由定时器准确控制。
- 单片机复位后,东西方向的绿灯从6秒倒计时;6秒后,东西方向的黄灯从3秒倒计时;3秒后,东西方向的红灯从9秒倒计时。单片机复位后,南北方向的红灯从9秒倒计时;9秒后,南北方向的绿灯从6秒倒计时。然后以上述方式循环显示。
- 单击K1键,恢复位置后的状态。K二键,停止,即LED发光二极管和LED点阵显示屏的状态保持不变。单片机停止后,单击K3键,继续运行刚才的状态。
仿真图
效果图
完整代码(C语言)
#include <reg52.h> #define uchar unsigned char #define uint unsigned int #define f1(a) (65536-a)/256 #define f2(a) (65536-a)%256 uchar code table[]={ 0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */ 0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* */ 0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, / */ 0xEF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF, /* */ 0xC3,0xFB,0xFB,0xFB,0xC3,0xDF,0xDF,0xC3, /* 红灯9秒 */ 0xC3,0xFB,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3, /* */ 0xC3,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF, /* */ 0xC1,0xDD,0xDD,0xC1,0xDD,0xDD,0xDD,0xC1, /* */ 0xC1,0xDD,0xDD,0xC1,0xDF,0xDF,0xDD,0xC1, /* */ 0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */ 0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* 黄灯3秒 */ 0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, /* */ 0xE7,0xEB,0xEF,0xEF,0xEF,0xEF,0xEF,0x83, /* */ 0xC7,0xB7,0xBB,0xDF,0xEF,0xF7,0xFB,0x83, /* */ 0xE3,0xDF,0xDF,0xE3,0xDF,0xDF,0xC3,0xFF, /* */ 0xEF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xEF, /* 绿灯6秒 */ 0xC3,0xFB,0xFB,0xFB,0xC3,0xDF,0xDF,0xC3, /* */ 0xC3,0xFB,0xFB,0xFB,0xC3,0xDB,0xDB,0xC3, /* */ }; uchar sec=17; sbit K1=P1^3; //将P1.3定义为K1 sbit K2=P1^4; //将P1.4定义为K2 sbit K3=P1^5; //将P1.5定义为K3 void delay(uint t); void Init(); void LatticDisplay(uchar num); void Light(uchar num); void keyscan(); void delay(uint t) //延时函数 { uchar i; while(t--) { for(i=0;i<120;i++); } } void Init() //初始化函数 { TMOD=0x01; //只是用定时器T0,使用计数功能 TH0=f1(1000); //高8位初始化 TL0=f2(1000); //地8位初始化 //1ms进入一次中断函数 EA=1; //中断总
开关开启 ET0=1; //T0定时器中断开关开启 TR0=1; //允许T0定时器工作标志位打开 } void LatticDisplay(uchar num)//点阵屏显示数字函数 { uchar i,j; for(i=0;i<8;i++) { P1=i|0xf8; //将P1口的高5位置1 P0=table[8*num+i]; //显示P0接的点阵屏第i行的亮点情况 if(8*(num-9)+i<0)//求出P2接口点阵屏亮的条件 j=8*(num+9)+i; else j=8*(num-9)+i; P2=table[j]; //显示P2接的点阵屏幕第i行的亮点情况 delay(4); //延迟4ms,4*8=32ms<50ms 满足视觉余辉效应 P0=0xff; //避免出现点阵有残影 P2=0xff; } } void Light(uchar num)//交通灯亮的函数 { uchar state_E_W,state_S_N; if(num>=12&&num<=17)// state_E_W=0x04; // if(num>=9&&num<=11) // 东西方向交通灯根据时间亮不同的颜色 state_E_W=0x02; // if(num>=0&&num<=8) // state_E_W=0x01; // if(num>=9&&num<=17) // state_S_N=0x08; // if(num>=0&&num<=2) // 南北方向交通灯根据时间亮不同的颜色 state_S_N=0x10; // if(num>=3&&num<=8) // state_S_N=0x20; // P3=state_E_W|state_S_N; //东西方向和南北方向交通灯情况互不干扰地写入P3,由P3输出 } void keyscan()//键盘检测函数 { if(K2==0)//判断K2按键是否被按下 { delay(20);//适当延迟,起到消抖作用 if(K2==0)//再次判断K2是否被按下,这是如果检测到被按下那就是真的被按下了 { TR0=0;//允许T0定时器工作标志位关闭 } } if(K3==0&&TR0==0)//判断K3是否被按下且允许T0定时器工作标志位关闭 { delay(20); if(K3==0&&TR0==0) { TR0=!TR0;//允许T0定时器工作标志位打开 } } if(K1==0)//判断K1按键是否被按下 { delay(20); if(K1==0) { Init();//单片机设置初始化 sec=17;//单片机设置初始化 } } } void main() { Init(); while(1) { LatticDisplay(sec); Light(sec); keyscan(); } } void timer0(void) interrupt 1 //定时器T0的中断函数,接口是1 { uint k; TH0=f1(1000); //高8位初始化 TL0=f2(1000); //低8位初始化 //1ms进入一次中断函数 k++; if(k==1000) //判断是否进入中断函数1000次 { //进入中断函数1000次需要1s k=0; //将记录进入中断函数的变量置0 sec--; //秒数-1 if(sec==-1)//判断秒数是否为-1 { sec=17; //将秒数复位,即17~0为一个周期 } } }