一、基本原理
利用51单片机控制各个路口红绿灯及时间显示。
设计的重点:
1、各个路口红绿灯亮灭的规则,暂不考虑左转方向;
2、倒计时的实现,利用单片机的定时器进行计数得到秒信号;
3、时间显示:东西南北四个方向的时间一致,当东西方向为60秒绿灯通行时间,同时南北方向为60秒红灯禁止时间,因此硬件连接时可考虑东西南北方向可采用同一接法;最后相当于2个数码管动态显示。
4、按键设置(扩展要求):设置键按一次,设置主干道通信时间(即次干道禁止时间),按第二次,设置主干道禁止时间(即次干道通信时间),按第三次,可作为紧急通信键。设置时间需要确定,可通过确定键实现,也可通过延时确定,如10秒。当然也可根据需要增加相应的按键。
仿真图
注意修改每个灯的管脚,位选管脚等。
#include <REGX52.H>
#define ON 0
#define OFF 1
unsigned char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
short EW_Time=60,NS_Time=60,EW_SetTime=60,NS_SetTime=60;
unsigned char Time_Mode=0,Flag_Blink=0;
sbit Switch_Time1=P3^3;//数码管位选
sbit Switch_Time2=P3^2;
sbit EW_Red=P2^0; //东西向红灯
sbit EW_Green=P2^3; //东西向绿灯
sbit EW_Yellow=P2^2; //东西向黄灯
sbit NS_Red=P2^5; //南北向红灯
sbit NS_Green=P2^7; //南北向绿灯
sbit NS_Yellow=P2^6; //南北向黄灯
sbit Power=P2^4;void delay_ms(unsigned int ms)//ms延时函数
{
unsigned int i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void Timer_Init()//定时器初始化
{
TMOD=0x01; //设置为定时器0工作模式1
TL0=(65536-50000)%256;//低八位
TH0=(65536-50000)/256;//高八位
TR0 = 1; //定时器0开始计时
EA=1;//开启总中断
ET0=1;//开启定时器0中断
}
void Nixie(unsigned char Data)//数码管显示
{
Switch_Time1=1;
Switch_Time2=0;
P0=tab[Data%10];//显示个位
delay_ms(1);
Switch_Time2=1;
Switch_Time1=0;
P0=tab[Data/10];//显示十位
delay_ms(1);
}
unsigned char Scan_Key()//获取按键键码
{
unsigned char KeyNumber=0;
if(P1_0==0){delay_ms(10);while(P1_0==0);delay_ms(10);KeyNumber=1;}
if(P1_1==0){delay_ms(10);while(P1_1==0);delay_ms(10);KeyNumber=2;}
if(P1_2==0){delay_ms(10);while(P1_2==0);delay_ms(10);KeyNumber=3;}
if(P1_3==0){delay_ms(10);while(P1_3==0);delay_ms(10);KeyNumber=4;}
if(P1_4==0){delay_ms(10);while(P1_4==0);delay_ms(10);KeyNumber=5;}
if(P1_5==0){delay_ms(10);while(P1_5==0);delay_ms(10);KeyNumber=6;}
if(P1_6==0){delay_ms(10);while(P1_6==0);delay_ms(10);KeyNumber=7;}
if(P1_7==0){delay_ms(10);while(P1_7==0);delay_ms(10);KeyNumber=8;}
return KeyNumber;
}
void traffic()//红绿灯主要逻辑
{
if(Time_Mode==0)//东西南北转换
{
Nixie(EW_Time);
if(EW_Time>5)
{
EW_Red=OFF;//东西红灯灭
NS_Yellow=OFF;//南北黄灯灭
NS_Green=OFF;//南北绿灯灭
EW_Green=ON;//东西绿灯亮
NS_Red=ON;//南北红灯亮
}else if(Flag_Blink==0&&EW_Time<=5&&EW_Time>0)//闪烁
{
EW_Green=OFF;//东西绿灯灭
EW_Yellow=ON;//东西黄灯亮
}else
{
EW_Green=OFF;//东西绿灯灭
EW_Yellow=OFF;//东西黄灯灭
}
}
if(Time_Mode==1)//东西南北转换
{
Nixie(NS_Time);
if(NS_Time>5)
{
NS_Red=OFF;//南北红灯灭
EW_Yellow=OFF;//东西黄灯灭
EW_Green=OFF;//东西绿灯灭
EW_Red=ON;//东西红灯亮
NS_Green=ON;//南北绿灯亮
}else if(Flag_Blink==0&&NS_Time<=5&&NS_Time>0)//闪烁
{
NS_Green=OFF;//南北绿灯灭
NS_Yellow=ON;//南北黄灯亮
}
else
{
NS_Green=OFF;//南北绿灯灭
NS_Yellow=OFF;//南北黄灯灭
}
}
}
void Set_Time()
{
char Key_Num=0,Key_Value=0,mode=1;
while(1)
{
Key_Value=Scan_Key();//获取键值
if(Key_Value!=0)Key_Num=Key_Value;
if(Key_Num==1)
{
mode++;
if(mode>3)break;
Key_Num=0;
}
if(mode==1)//按下第二次显示东西通讯时间,可加减设置
{
Nixie(EW_SetTime);
if(Key_Num==2){EW_SetTime++;Key_Num=0;}
if(Key_Num==3){EW_SetTime--;Key_Num=0;}
}
if(mode==2)//按下第二次显示南北通讯时间,可加减设置
{
Nixie(NS_SetTime);
if(Key_Num==2){NS_SetTime++;Key_Num=0;}
if(Key_Num==3){NS_SetTime--;Key_Num=0;}
}
if(mode==3)//按下第三次时显示00,红灯亮,紧急通行
{
P2=0xFF;
Nixie(0);
NS_Red=ON;
EW_Red=ON;
}
if(Key_Num==4)//确认键,上传主副干道通行时间
{
EW_Time=EW_SetTime;
NS_Time=NS_SetTime;
break;
}
}
}
void Yellow_Blink()//黄灯闪烁
{
char Key_Num=0,Key_Value=0,Mode=1;
while(1)
{
Key_Value=Scan_Key();//获取键值
if(Key_Value!=0)Mode=Key_Value;
P2=0xFF;
Nixie(0);
if(Flag_Blink)
{
EW_Yellow=ON;
NS_Yellow=ON;
}else
{
EW_Yellow=OFF;
NS_Yellow=OFF;
}
if(Mode==5){break;}
}
}
void main()
{
char Key_Mode=0,Key_Value=0;
P2=0xFF;
Power=1;
Timer_Init();//初始化定时器
// NS_Green=OFF;
while(1)
{
Key_Value=Scan_Key();
if(Key_Value!=0)Key_Mode=Key_Value;
switch(Key_Mode)
{
case 0:traffic();
break;
case 1:Set_Time();
Key_Mode=0;
break;
case 5:Yellow_Blink();
Key_Mode=0;
break;
default:
Key_Mode=0;
}
}
}
void Timer0() interrupt 1
{
static unsigned char count=0,count1=0;
TL0=(65536-50000)%256;//低八位
TH0=(65536-50000)/256;//高八位
if(count>=10)
{
count=0;
if(Time_Mode==0)//东西时间减
{
EW_Time--;
if(EW_Time<0){EW_Time=EW_SetTime;Time_Mode=!Time_Mode;}
}
if(Time_Mode==1)//南北时间减
{
NS_Time--;
if(NS_Time<0){NS_Time=NS_SetTime;Time_Mode=!Time_Mode;}
}
}
if(count1>=5)//闪烁标志位
{
count1=0;
Flag_Blink=!Flag_Blink;
}
count++;
count1++;
}