交通灯,仅供参考!
交通灯仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h>
- bit red,green,yellow,turnred; //定义红、黄、绿及转红标志
- code unsigned char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f}; //共阴极数码管码表
- #define LIGHT P0
- #define SEG P1
- #define BITR P2
- unsigned char Dis_Shiwei;//定义十位
- unsigned char Dis_Gewei; //定义个位
- unsigned char second,count=0; //初值60
- #define uchar unsigned char
- #define uint unsigned int
- sbit add=P3^3; //定义东西绿灯时间加按键
- sbit sub=P3^4; //定义东西绿灯时间减按键
- sbit K1=P3^1; //定义设定时间按键
- sbit add2=P3^5; //定义调南北绿灯时间加按键
- sbit sub2=P3^6; //定义调南北绿灯时间减按键
- unsigned char timeDX=13,timeNB=15; //定义东西和南北绿灯亮时可调变量并赋予初值2S
- void delay(unsigned int cnt) //用于动态扫描数码管的延时程序
- {
- while(--cnt);
- }
- /*********************************延时子程序*************************************/
- void DelayMS(unsigned int x) //延时ms
- {
- unsigned char t;
- while(x--)
- {
- for(t=120;t>0;t--);
- }
- }
- void key_scan( )
- {
- uchar s1num=0; //s1num记录光标的位置的编号
-
- if(K1==0)
- {
- DelayMS(5);
- if(K1==0)
- {
- while(!K1); //menum测试到由0到1的变化,也就是按下松开的变化,s1num加1
- s1num++;
- while(1)
- {
- if(K1==0)
- {
- DelayMS(5);
- if(K1==0)
- {
- while(!K1);
- s1num++; //menum测试到由0到1的变化,也就是按下松开的变化,s1num再加1
- }
- }
-
-
- if(s1num==1)
- {
-
-
- while(add==0) //如果第一个按键按下东西方向绿灯延续时间加1秒
- {
- DelayMS(10);
- while(add==0);
- timeDX++;
- if(timeDX>60) //当时间超过60秒将时间置为60秒
- {timeDX=0;}
- Dis_Shiwei=tab[timeDX/10];//十位显示值处理
- Dis_Gewei=tab[timeDX%10]; //个位显示处理
- }
- while(sub==0) //如果第二个按键按下东西方向绿灯延续时间减1秒
- {
- DelayMS(10);
- while(sub==0);
- timeDX--;
- if(timeDX<=0) //当时间减到小于或等于0时将时间置为1秒
- {timeDX=60;}
- Dis_Shiwei=tab[timeDX/10];//十位显示值处理
- Dis_Gewei=tab[timeDX%10]; //个位显示处理
- }
- while(add2==0) //如果第三个按键按下南北方向绿灯延续时间加1秒
- {
- DelayMS(10);
- while(add2==0);
- timeNB++;
- if(timeNB>60) //当时间超过60秒将时间置为60秒
- {timeNB=0;}
- Dis_Shiwei=tab[timeNB/10];//十位显示值处理
- Dis_Gewei=tab[timeNB%10]; //个位显示处理
- }
- while(sub2==0) //如果第四个按键按下南北方向绿灯延续时间减1秒
- {
- DelayMS(10);
- while(sub2==0);
- timeNB--;
- if(timeNB<=0) //当时间减到小于或等于0时将时间置为1秒
- {timeNB=60;}
- Dis_Shiwei=tab[timeNB/10];//十位显示值处理
- Dis_Gewei=tab[timeNB%10]; //个位显示处理
- }
- }
- if(s1num==2)
- {
- s1num=0;//s1num清零//
- break;
- }
- }
- }
- }
- }
- void LINGHTLED( )
- {
- if (count==100)
- {
- count=0;
- second--;//秒减1
- if(second==0)
- { //这里添加定时到0的代码 ,可以是灯电路,继电器吸合等,或者执行一个程序
- if(red) //红灭,先转黄
- {
- red=0;
- yellow=1;
- second=4;
- LIGHT=0xdd;//黄灯亮4秒,黄灯为过渡灯,再根据情况转绿或转红
- while(K1==0);
- }
- else if(yellow && !turnred)
- {
- yellow=0;
- green=1;
- second=timeDX;
- LIGHT=0xf3;//绿灯亮25秒,
- while(K1==0);
- }
- else if(green)
- {
- yellow=1;
- green=0;
- second=4;
- LIGHT=0xeb;//黄灯亮4秒
- while(K1==0);
- turnred=1;
- }
- else if(yellow && turnred) //绿灯灭,转黄灯,后红灯,turnred=1时
- {
- red=1;
- yellow=0;
- LIGHT=0xde;//红灯亮60秒
- while(K1==0);
- second=timeNB;
- turnred=0; //接下来是转黄,绿。
- }
- }
- }
- Dis_Shiwei=tab[second/10];//十位显示值处理
- Dis_Gewei=tab[second%10]; //个位显示处理
- }
- void inti( )
- {
- TMOD |=0x11;//定时器设置 10ms in 12M crystal定时器0,工作方式1,16位定时器
- TH0=0xd8; //65535-10000=55535=D8F0(十六进制)
- TL0=0xf0;
- IE= 0x8A; //中断控制,EA=1开总中断,ET0=1:定时器0中断允许
- IP=0x02;
- TR0=1; //开定时器0中断
- TR1=1; //开定时器0中断
- }
- void main()
- {
-
- inti( );
- LIGHT=0xde;//红灯亮,根据红黄绿接灯的顺序。
- red =1;
- second=timeDX;
- while(1)
- {
- key_scan();//键盘扫描程序
-
- LINGHTLED( );
- }
- }
- /********************************/
- /* 定时中断 */
- /********************************/
- void tim(void) interrupt 1
- {
- TH0=(65536-10000)/256;//重新赋值,10毫秒定时
- TL0=(65536-10000)%256;;
- count++;
- }
- /********************************/
- /* 定时中断 */
- /********************************/
- void tim2(void) interrupt 3
- {
- TR1=0;
- TH1=(65536-5000)/256;//重新赋值,5毫秒定时
- TL1=(65536-5000)%256;;
-
- BITR=0xfE;
- SEG=Dis_Shiwei;//显示十位,这里实现用8位数码管,即左1位
- delay(30);//短暂延时
- BITR=0XfD;
- SEG=Dis_Gewei; //显示个位,左数,2位
- delay(30);
- TR1=1;
- …………
- …………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
交通灯.rar
(53.16 KB, 下载次数: 49)
|