基于 C51 芯片单片机简易交通灯设计
前言
单片机期末课程设计搞了一个最简单的交通灯,大概记录一下。
概要设计
详细设计
初始化定时器&外部中断
TMOD=0X11
定时器模式 1 ,组成一个 16 位的定时器晶振频率为 11.0592M 时,定时 50ms 的初值为 0x4c、0x00 :
1
2
3
4TH1=0x4C; //TH1重赋初值;11.0592m晶振50ms
TL1=0X00;
TH0=0x4C; //TH0重赋初值;11.0592m晶振50ms
TL0=0X00;启动定时0、定时1:
TCON=0X50
开总中断;定时器1中断开启;开外部中断1;定时器0中断开启;开外部中断:
IE=0x8F
初始化信号灯开关、时间:
1
2
3P2=0Xc3; //开始默认状态,东西绿灯,南北黄灯
sec_nb=35; //南北方向初始时间
sec_dx=30;
程序主循环
倒计时处理部分放在定时器中断服务中,buf 中的数字会不断刷新,主函数只需循环调用显示函数,显示倒计时。除此之外还判断是否进入特殊模式,特殊模式标志位是由外部中断修改:
1 | void main() |
信号灯计时
使用定时器中断0循环计数 20 次记为 1 秒,当计数等于 20 时,进入处理倒计时数字处理逻辑部分。进入后首先重置计数器,然后各个方向时间 -1 :
1 | if(countt0==20) //定时器中断次数=20时(即1秒时) |
时间 -1 后需要进一步判断是否需要切换状态。需要处理的有两种:
- 黄灯频闪:非通行方向时间剩余 5 秒,通行方向时间剩余 0 秒
- 切换通行方向:通行方向时间剩余 0 秒,非通行方向时间剩余 0 秒,且已经在黄灯频闪状态
黄灯频闪
进入条件:任意一个方向时间剩余 5 秒且另外一个方向时间剩余 0 秒,黄灯闪烁标志为 0 。
处理方法是将通行方向增加 5 秒用于黄灯频闪:
1 | if(sec_nb==0&&sec_dx==5&&(Yellow_status==0)) //当南北倒计时到0时,重置5秒,用于黄灯闪烁时间 |
进入黄灯闪烁模式后,判断通行方向,关闭通行方向绿灯、取反黄灯状态。
1 | if((sec_dx<=5)&&(dx_nb==1)&&(Yellow_status==1)) //南北黄灯闪 |
另外一个方向的处理逻辑一致。
切换通行方向
进入条件:当非通行方向黄灯时间、通行方向倒计时到0时
1 | if(dx_nb==1&&sec_dx==0&&sec_nb==0) //南北通行:当黄灯时间、通行方向倒计时到0时 |
功能函数
紧急模式
全部方向红灯
用外部中断0改变全局标志位来进入函数:
1 | void int0(void) interrupt 0 using 1 //禁止通行 |
处理逻辑:关交通灯定时器、灭显示、全部置红灯
1 | TR0=0; //关交通灯定时器 |
恢复逻辑:
1 | TR0=1; //开交通灯定时器 |
通过一个计数器实现进入与恢复:
1 | conut_ER=1-conut_ER; |
夜间模式
全部方向黄灯频闪
处理逻辑大致与上面一样,差异是控制频闪放在定时器中断1服务中。这里功能函数修改一个全局标志位,让定时器1启动输出。
1 | conut_night=1-conut_night; |
定时器1中断服务,控制黄灯每 0.5 s 反转一次:
1 | /*用来处理夜间黄灯闪烁*/ |
演示截图
模拟电路电路图:
信号控制演示
紧急模式
夜间模式
Github 仓库
该项目托管在Github@skyedai910/traffic-lights-BC
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SkYe231 Blog!