这是写完的交通灯程序,在单片机上是能用的。因为很多时候单片机上能跑的程序在PROTEUS上不能跑,所以我没有搭建仿真,也不是用PCB板,只是在实验板上跑了一下,是能用的。具体实现的功能有
显示红绿灯:初始化状态为一向60s,另一向40s开始倒计时。然后,40s走完后,再走20s,然后就两向换倒计时的秒数。
现在有两个按键有具体功能:一个是按下停止刷新,再按一次继续刷新;一个是模式切换按键,按一下,为紧急模式,再按一下为正常模式,再按一下为特殊模式;重复按三下后转为初始化模式。代码在下面,希望对群友有用。
单片机源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- typedef unsigned int u16;
- typedef unsigned char u8;
- u8 digtub[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //用于实物显示的0~9
- //u8 digtub[]={0xC0,0xf9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //用于Proteus显示用的0~9
- u8 dat[8];//欲显示的数据
- sbit LSA=P2^2;
- sbit LSB=P2^3;
- sbit LSC=P2^4;//以上三个是数码管位选位
- sbit lred=P2^0;//东西方红灯
- sbit lgreen=P3^4;//东西方绿灯
- sbit lyellow=P2^7;//东西方黄灯
- sbit rred=P2^5; //南北方红灯
- sbit rgreen=P2^1;//南北方绿灯
- sbit ryellow=P2^6;//南北向黄灯
- sbit KEY1=P3^1; //按键1
- sbit KEY2=P3^2; //按键2
- sbit KEY3=P3^3; //按键3
- sbit KEY4=P3^0;
- #define RRED(x) {if((x))rred=0;else{rred=1;}} //南北向红灯开关函数
- #define LRED(x) {if((x))lred=0;else{lred=1;}} //东西向红灯开关函数
- #define RGREEN(x) {if((x))rgreen=0;else{rgreen=1;}} //南北向绿灯开关函数
- #define LGREEN(x) {if((x))lgreen=0;else{lgreen=1;}} //东西向绿灯开关函数
- #define RETURN_RYELLOW {ryellow=~ryellow;} //南北向黄灯闪烁函数
- #define RETURN_LYELLOW {lyellow=~lyellow;} //东西向黄灯闪烁函数
- sbit L1=P3^4;
- sbit L2=P3^5;
- void key_init();
- void display();
- void vestmode();
- /********************************************************************************************
- ************************定时初始化函数**********************************************************/
- void timer_init()
- {
- TMOD|=0X01;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- TR0=1;
- EA=1;
- ET0=1;
- }
- /*********************************************************************************************************
- ************************以上是定时初始化函数**********************************************************/
- /***************************************************************************************************
- ************************以下是延时函数***************************************************************/
- void delay(u16 ms)
- {
- u16 i;
- for(ms;ms>0;ms--)
- {
- for(i=0;i<120;i++);
- }
- }
- /***************************************************************************************************
- ************************以上是延时函数***************************************************************/
- u16 opendis;
- void main()
- {
- timer_init();
- while(1)
- {
- if(!opendis)display();
- key_init();
- vestmode();
- }
- }
- bit givenum;//开关红绿灯秒数赋值的标志位
- u16 staticgreen=30; //固定绿灯值可通过按键修改
- u16 staticred=10; //固定红灯值可通过按键修改
- u8 NSNUM[3]={40,20,60}; //南北方向红绿灯秒数[1]红灯;[2]右转红灯;[3]绿灯
- u8 EWNUM[3]={60,20,40}; //东西方向红绿灯秒数[1]绿灯;[2]红灯;[3]右转红灯
- /**********************
- 这个是定时中断函数************/
- void time0() interrupt 1
- {
- static u16 num=0;
- static u8 ewnum;//东西方向60s绿灯
- static u8 nsnum;//南北方向40s红灯
- static u16 nsflag=0;//南北向黄灯次数或转换红绿方向的标志
- static u16 ewflag=0;//东西向黄灯次数或转换红绿方向的标志
- u16 Rgreen,Lgreen; //Rgreen南北向绿灯灭标志 ;Lgreen东西向绿灯灭标志;lreturn右转红灯值(方便修改)
- if(!givenum){ewnum=EWNUM[0];nsnum=NSNUM[0];}//二次赋值,为了方便修改
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- num++; //num=20时刚好计数是1s。
- if(num==20)
- {
- givenum=1;
- num=0;
- ewnum--;
- nsnum--;
- if(nsnum==0){if(nsflag>=2){nsflag=0;RGREEN(0);}else{nsflag++;}nsnum=NSNUM[nsflag];}//南北向数码管循环显示。
- if(ewnum==0){if(ewflag>=2){ewflag=0;}else{ewflag++;}ewnum=EWNUM[ewflag];}//东西向数码管循环显示。
- if(nsflag==0||nsflag==1){RRED(1);}//南北向直行或右转时的红灯
- if(nsnum>0&&nsnum<5){
- RETURN_RYELLOW;
- RRED(0);RGREEN(0);Rgreen=1;//南北向红绿灯都灭
- }//大于0小于5时黄灯
- if(nsflag==2&&!Rgreen){RGREEN(1);}//南北绿灯
- if(ewflag==0||ewflag==1){LRED(1);}//东西向直行或右转时的红灯
- if(ewnum>0&&ewnum<5){
- RETURN_LYELLOW;
- LRED(0);LGREEN(0);Lgreen=1;//东西向红绿灯都灭
- }//大于0小于5时黄灯
- if(ewflag==2&&!Lgreen){LGREEN(1);}//南北绿灯
- dat[0]=digtub[ewnum/10];//东西方向红绿灯的十位
- dat[1]=digtub[ewnum%10];//东西方向红绿灯的个位
- dat[2]=digtub[nsnum/10];
- dat[3]=digtub[nsnum%10];
- dat[6]=digtub[ewnum/10];//东西方向红绿灯的十位
- dat[7]=digtub[ewnum%10];//东西方向红绿灯的个位
- dat[4]=digtub[nsnum/10];
- dat[5]=digtub[nsnum%10];
- }
- }
- /********************上面是定时中断函数*******************
- *********************************************/
- /*这个是按键程序*******************************************************
- ***************************************************************************/
- static u16 modesign[6]={1,2,3};//模式选择标志
- static u16 keymode;
- static u16 ewgreen;
- u16 ll;
- void key_init()
- {
- static u16 i=0;
- if(KEY1==0)//开关数码管显示按键
- {
- delay(100);
- if(KEY1==0){TR0=~TR0;}
- while(!KEY1);
- }
- if(KEY2==0) //切换模式按键
- {
- delay(100);
- if(KEY2==0){
- keymode=modesign[i++];
- if(i>3){i=0;}
- }
- while(!KEY2);
- }
- if(KEY3==0)//后台修改红绿灯值,
- {
- delay(100);
- if(KEY3==0);
- while(!KEY3);
- }
- if(KEY4==0)//后台修改红绿灯值,
- {
- delay(100);
- if(KEY4==0);
- while(!KEY4);
- }
- }
- /***********************************************************************************************/
- /***************************************************************************************************/
- void display()
- {
- u16 i;
- for(i=0;i<8;i++)
- {
- switch(i)
- {
- case 0:LSA=0;LSB=0;LSC=0;P0=dat[1];break; //第一个数码管
- case 1:LSA=1;LSB=0;LSC=0;P0=dat[0];break; //第二个数码管
- case 2:LSA=0;LSB=1;LSC=0;P0=dat[5];break;//第三个数码管
- case 3:LSA=1;LSB=1;LSC=0;P0=dat[4];break; //第四个数码管
- case 4:LSA=0;LSB=0;LSC=1;P0=dat[7];break; //第五个数码管
- case 5:LSA=1;LSB=0;LSC=1;P0=dat[6];break; //第六个数码管
- case 6:LSA=0;LSB=1;LSC=1;P0=dat[3];break; //第七个数码管
- case 7:LSA=1;LSB=1;LSC=1;P0=dat[2];break; //第八个数码管
- }
- }
- }
- /***************************************************************************************************
- ****************************************************************************************************
- ***********************************************************************************************/
- void vestmode() //切换模式按键:keymode:1 紧急模式 ; 2 正常模式;3 特殊模式
- {
- if(keymode==1){
- EWNUM[0]=45;EWNUM[1]=30;EWNUM[2]=15;
- NSNUM[0]=30;NSNUM[1]=15;NSNUM[2]=45;
- givenum =0;
- keymode=0;
- }
- if(keymode==2){
- EWNUM[0]=60;EWNUM[1]=40;EWNUM[2]=20;
- NSNUM[0]=40;NSNUM[1]=20;NSNUM[2]=60;
- givenum =0;
- keymode=0;
- }
- if(keymode==3) //特殊模式后,继续按3次,会初始化到正常模式
- {
- opendis=~opendis;
- keymode=0;
- }
- }
- /***************************************************************************************************
- ****************************************************************************************************
- ***********************************************************************************************/
复制代码
所有程序51hei提供下载:
交通灯.rar
(71.28 KB, 下载次数: 8)
|