找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1105|回复: 0
打印 上一主题 下一主题
收起左侧

交通灯控制

[复制链接]
跳转到指定楼层
楼主
ID:272466 发表于 2018-1-6 18:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

#include<reg51.h>

#defineuchar unsigned char

#defineuint  unsigned int


uchardata buf[4];

uchardata sec_dx=20;           //东西数默认

uchardata sec_nb=30;           //南北默认值

uchardata set_timedx=20;       //设置东西方向的时间

uchardata set_timenb=30;       //设置南北方向的时间

intn,led1=0;

uchardata countt0;//定时器0中断次数

sfrWDT_CONTR=0xA6;

//定义5组开关

sbit  k4=P3^7;     //切换方向

sbit  k1=P3^5;       //时间加

sbit  k2=P3^6;       //时间减

sbit  k3=P3^4;       //确认

sbit  k5=P3^1;       //禁止

sbit  k6=P1^5;       //夜间模式

//       P3^2     //只允许东西方向通行,中断0

//       P3^3     //只允许南北方向通行,中断1


sbitRed_nb=P2^6;    //南北红灯标志

sbitYellow_nb=P2^5; //南北黄灯标志

sbitGreen_nb=P2^4;     //南北绿灯标志


sbitRed_dx=P2^3;    //东西红灯标志

sbitYellow_dx=P2^2; //东西黄灯标志

sbitGreen_dx=P2^1;      //东西绿灯标志

   

sbitBuzz=P3^0;      

bitBuzzer_Indicate;

bitset=0;           //调时方向切换键标志 =1时,南北,=0时,东西

bitdx_nb=0;         //东西南北控制位

bitshanruo=0;


ucharcode table[11]={   //共阴极字型码

    0x3f, //--0

    0x06, //--1

    0x5b, //--2

    0x4f, //--3

    0x66, //--4

    0x6d, //--5

    0x7d, //--6

    0x07, //--7

    0x7f, //--8

    0x6f, //--9

    0x00  //--NULL

};


//函数的声明部分

voiddelay(int ms);         //延时子程序

voidkey();                 //按键扫描子程序

voidkey_to1();             //键处理子程序

voidkey_to2();

voidkey_to3();

voiddisplay();             //显示子程序

voidlogo();                //开机LOGO

voidBuzzer();

//主程序

voidmain()

{

    TMOD=0X11;               //定时器设置

    TH0=0X3C;                //定时器0置初值 0.05S

    TL0=0XB0;

    EA=1;                    //开总中断

    ET0=1;                   //定时器0中断开启

    TR0=1;                   //启动定时0

    EX0=1;                   //开外部中断0

    EX1=1;                   //开外部中断1

    logo();

    P2=0Xc3;                 //开始默认状态,东西绿灯,南北黄灯   

    sec_nb=sec_dx+5;            //默认南北通行时间比东西多5秒

    while(1)

    {   

       key();                   //调用按键扫描程序

       display();               //调用显示程序

       Buzzer();

    }   

}

//函数的定义部分

voidkey(void)    //按键扫描子程序

{   

    if(k1!=1)                       //当K1(时间加)按下时

    {

       display();                  //调用显示,用于延时消抖

       if(k1!=1)            

       {

           TR0=0;                      //关定时器

           shanruo=0;

           P2=0x00;

           if(set==0)

              set_timedx++;        //南北加1S

           else

              set_timenb++;        //东西加1S

           if(set_timenb==100)

              set_timenb=1;

           if( set_timedx==100)

              set_timedx=1;        //加到100置1

           sec_nb=set_timenb ;      //设置的数值赋给东西南北

           sec_dx=set_timedx;          //

           do

           {

              display();

           }

           while(k1!=1);

       }

    }


    if(k2!=1)                       //当K2(时间减)按键按下时

    {      

       display();                  //调用显示,用于延时消抖  

       if(k2!=1)

       {   

           TR0=0;                     //关定时器

           shanruo=0;

           P2=0x00;

           if(set==0)

               set_timedx--;            //南北减1S

           else

              set_timenb--;            //东西减1S

           if(set_timenb==0)

              set_timenb=99;   

           if( set_timedx==0)

              set_timedx=99;       //减到1重置99

           sec_nb=set_timenb ;         //设置的数值赋给东西南北

           sec_dx=set_timedx;

           do  

          {

              display();           //调用显示,用于延时

           }

           while(k2!=1);

       }

    }


    if(k3!=1)                       //当K3(确认)键按下时

    {   

       display();                  //调用显示,用于延时消抖

       if(k3!=1)

       {

           TR0=1;                      //启动定时器

           Buzzer_Indicate=0;

           sec_nb=set_timenb;              //从中断回复,仍显示设置过的数值

           sec_dx=set_timedx;              //显示设置过的时间

           if(set==0)                  //时间倒时到0时

           {

              P2=0X00;                 //东西绿灯,南北红灯

              Green_dx=1;

              Red_nb=1;

              sec_nb=sec_dx+5;         //回到初值

           }

           else

           {

              P2=0x00;                 //南北绿灯,东西红灯

              Green_nb=1;

              Red_dx=1;

              sec_dx=sec_nb+5;

           }

       }

    }

     

    if(k4!=1)                       //当K4(切换)键按下

    {

       display();                  //调用显示,用于延时消抖

       if(k4!=1)

       {  

           TR0=0;

           set=!set;                //取反set标志位,以切换调节方向

           dx_nb=set;

           do

           {

              display();

           }            

           while(k4!=1);

       }

    }   


    if(k5!=1)                       //当K5(禁止)键按下时

    {

        display();                 //调用显示,用于延时消抖

        if(k5!=1)

        {   

           TR0=0;                   //关定时器

           P2=0x00;

           Red_dx=1;

           Red_nb=1;                //全部置红灯

           sec_dx=00;               //四个方向的时间都为00

           sec_nb=00;

           Buzzer_Indicate=1;   

           do

           {

              display();

           }   

           while(k5!=1);            

        }

    }

    if(k6!=1)                       //当K6(夜间模式)按下

    {

        display();                 //调用显示,用于延时消抖

        if(k6!=1)

        {   

           TR0=0;                   //关定时器

           P2=0x00;

           Yellow_dx=1;

           Yellow_nb=1;                //全部置黄灯

           sec_dx=00;               //四个方向的时间都为00

           sec_nb=00;

           Buzzer_Indicate=1;   

           do

           {

              display();

           }   

           while(k6!=1);            

        }

    }

}

voiddisplay(void) //显示子程序

{      

    buf[1]=sec_nb/10;        //第1位 东西秒十位

    buf[2]=sec_nb%10;        //第2位 东西秒个位

    buf[3]=sec_dx/10;        //第3位 南北秒十位

    buf[0]=sec_dx%10;        //第4位 南北秒个位      

    P1=0xff;                 //初始灯为灭的

    P0=0x00;

    P1=0xfe;                 //片选LED1

    P0=table[buf[1]];    //送东西时间十位的数码管编码

    delay(1);            //延时

    P1=0xff;             //关显示

    P0=0x00;            

   

    P1=0xfd;                 //片选LED2

    P0=table[buf[2]];

    delay(1);

    P1=0xff;

    P0=0x00;

    P1=0Xfb;             //片选LED3

    P0=table[buf[3]];

    delay(1);

    P1=0xff;

    P0=0x00;

    P1=0Xf7;

    P0=table[buf[0]];    //片选LED4

    delay(1);

}


voidtime0(void) interrupt 1 using 1   //定时中断子程序

{

    TH0=0X3C;                       //重赋初值

    TL0=0XB0;

    TR0=1;                          //重新启动定时器

    countt0++;                      //软件计数加1

    if(countt0==10)

    {

       if((sec_nb<=5)&&(dx_nb==0)&&(shanruo==1))        //东西黄灯闪      

        {

           Green_dx=0;

           Yellow_dx=0;

           Buzz=0;

       }                    

       if((sec_dx<=5)&&(dx_nb==1)&&(shanruo==1))        //南北黄灯闪      

        {

           Green_nb=0;

           Yellow_nb=0;

           Buzz=0;

       }   

    }

      

    if(countt0==20)                        // 定时器中断次数=20时(即1秒时)

    {   countt0=0;                  //清零计数器

       sec_dx--;                   //东西时间减1

       sec_nb--;                   //南北时间减1


       if((sec_nb<=5)&&(dx_nb==0)&&(shanruo==1))        //东西黄灯闪      

        {

           Green_dx=0;

           Yellow_dx=1;

           Buzz=1;

       }                    

       if((sec_dx<=5)&&(dx_nb==1)&&(shanruo==1))        //南北黄灯闪      

        {

           Green_nb=0;

           Yellow_nb=1;

           Buzz=1;

       }                          

       if(sec_dx==0&&sec_nb==5)        //当东西倒计时到0时,重置5秒,用于黄灯闪烁时间  

       {

           sec_dx=5;

           shanruo=1;

       }

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

       {

           sec_nb=5;

           shanruo=1;

       }

       if(dx_nb==0&&sec_nb==0)         //当黄灯闪烁时间倒计时到0时,

       {

           Buzz=1;

           P2=0x00;                 //重置东西南背方向的红绿灯

           Green_nb=1;

           Red_dx=1;

           dx_nb=!dx_nb;

           shanruo=0;

           sec_nb=set_timenb;          //重赋南北方向的起始值

           sec_dx=set_timenb+5;     //重赋东西方向的起始值

       }      

       if(dx_nb==1&&sec_dx==0)         //当黄灯闪烁时间到

       {

           P2=0X00;                 //重置东西南北的红绿灯状态

           Green_dx=1;

           Red_nb=1;

           dx_nb=!dx_nb;

           shanruo=0;

           sec_dx=set_timedx;          //重赋东西方向的起始值

           sec_nb=set_timedx+5;     //重赋南北方向的起始值

       }

    }   

}



//外部中断0

voidint0(void) interrupt 0 using 1       //只允许东西通行

{

    TR0=0;                          //关定时器

    P2=0x00;

    Green_dx=1;                        //东西方向置绿灯

    Red_nb=1;                       //南北方向为红灯

    Buzzer_Indicate=0;

    sec_dx=00;                      //四个方向的时间都为00

    sec_nb=00;

}


//外部中断1

voidint1(void) interrupt 2 using 1         //只允许南北通行

{

    TR0=0;                          //关定时器

    P2=0x00;

    Green_nb=1;                        //置南北方向为绿灯

    Red_dx=1;                       //东西方向为红灯

    Buzzer_Indicate=0;

    sec_nb=00;                      //四个方向的时间都为00

    sec_dx=00;

}

voidlogo()//开机的Logo  "- -- -"

{

    for(n=0;n<50;n++)

    {

       P0=0x40;

       P1=0xfe;

       delay(1);

       P1=0xfd;

       delay(1);

       P1=0Xfb;

       delay(1);

       P1=0Xf7;

       delay(1);

        P1= 0xff;

    }

}

void watchdog()        /*看门狗子函数*/

       {

         WDT_CONTR=0xE1;  /*喂狗指令*/

         led1=0;

         delay(500);

         led1=1;      

         while(1)

         {

                  delay(1000);

        }

    }

            


voidBuzzer()

{

   if(Buzzer_Indicate==1)

       Buzz=!Buzz;

   else Buzz=1;

}


voiddelay(int ms)       //延时子程序

{

    uint j,k;

    for(j=0;j<ms;j++)        //延时ms

      for(k=0;k<124;k++);      //大约1毫秒的延时
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表