前言

单片机期末课程设计搞了一个最简单的交通灯,大概记录一下。

概要设计

交通灯系统设计

详细设计

初始化定时器&外部中断

  1. TMOD=0X11 定时器模式 1 ,组成一个 16 位的定时器
  2. 晶振频率为 11.0592M 时,定时 50ms 的初值为 0x4c、0x00 :

    TH1=0x4C;                            //TH1重赋初值;11.0592m晶振50ms
    TL1=0X00;
    TH0=0x4C;                            //TH0重赋初值;11.0592m晶振50ms
    TL0=0X00;
  3. 启动定时0、定时1:TCON=0X50
  4. 开总中断;定时器1中断开启;开外部中断1;定时器0中断开启;开外部中断:IE=0x8F
  5. 初始化信号灯开关、时间:

    P2=0Xc3;                            //开始默认状态,东西绿灯,南北黄灯
    sec_nb=35;                            //南北方向初始时间
    sec_dx=30;    

程序主循环

倒计时处理部分放在定时器中断服务中,buf 中的数字会不断刷新,主函数只需循环调用显示函数,显示倒计时。除此之外还判断是否进入特殊模式,特殊模式标志位是由外部中断修改:

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

信号灯计时

使用定时器中断0循环计数 20 次记为 1 秒,当计数等于 20 时,进入处理倒计时数字处理逻辑部分。进入后首先重置计数器,然后各个方向时间 -1 :

if(countt0==20)                          //定时器中断次数=20时(即1秒时)
{    
    countt0=0;                        //清零计数器
    sec_dx--;                        //东西时间减1
    sec_nb--;                        //南北时间减1 

时间 -1 后需要进一步判断是否需要切换状态。需要处理的有两种:

  1. 黄灯频闪:非通行方向时间剩余 5 秒,通行方向时间剩余 0 秒
  2. 切换通行方向:通行方向时间剩余 0 秒,非通行方向时间剩余 0 秒,且已经在黄灯频闪状态

黄灯频闪

进入条件:任意一个方向时间剩余 5 秒且另外一个方向时间剩余 0 秒,黄灯闪烁标志为 0 。

处理方法是将通行方向增加 5 秒用于黄灯频闪:

if(sec_nb==0&&sec_dx==5&&(Yellow_status==0))        //当南北倒计时到0时,重置5秒,用于黄灯闪烁时间
{
    sec_nb=5;
    Yellow_status=1;
}

进入黄灯闪烁模式后,判断通行方向,关闭通行方向绿灯、取反黄灯状态。

if((sec_dx<=5)&&(dx_nb==1)&&(Yellow_status==1))          //南北黄灯闪
{
    Green_nb=0;
    Yellow_nb=~Yellow_nb;
}

另外一个方向的处理逻辑一致。

切换通行方向

进入条件:当非通行方向黄灯时间、通行方向倒计时到0时

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;            //重赋南北方向的起始值
        }

功能函数

紧急模式

全部方向红灯

用外部中断0改变全局标志位来进入函数:

void int0(void) interrupt 0 using 1        //禁止通行
{
    while(!key_EP)display();
    flag_option=1;
}

处理逻辑:关交通灯定时器、灭显示、全部置红灯

TR0=0;                        //关交通灯定时器
P2=0x00;                    //灭显示
Red_dx=1;                   //全部置红灯
Red_nb=1;

恢复逻辑:

TR0=1;                        //开交通灯定时器
P2=0X00;                    //关全部信号灯
Green_dx=1;                    //东西绿灯亮
Red_nb=1;                    //南北红灯亮
sec_dx=set_timedx;          //回到初值
sec_nb=sec_dx+5;

通过一个计数器实现进入与恢复:

conut_ER=1-conut_ER;
if(conut_ER==1){}        
if(conut_ER==0){}    

夜间模式

全部方向黄灯频闪

处理逻辑大致与上面一样,差异是控制频闪放在定时器中断1服务中。这里功能函数修改一个全局标志位,让定时器1启动输出。

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;

定时器1中断服务,控制黄灯每 0.5 s 反转一次:

/*用来处理夜间黄灯闪烁*/
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;        //东西黄灯
        }
    }
}

演示截图

  1. 模拟电路电路图:

  2. 信号控制演示

  3. 紧急模式

  4. 夜间模式

Github 仓库

该项目托管在[email protected]skyedai910/traffic-lights-BC

Last modification:July 2nd, 2020 at 09:05 am