#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit wela = P2^7; // 数码管位选
sbit dula = P2^6; // 数码管段选
// 下面是八个交通灯对应的位定义
sbit LED1_blue = P1^0;
sbit LED1_red = P1^1;
sbit LED1_green = P1^2;
sbit LED1_yellow = P1^3;
sbit LED2_blue = P1^4;
sbit LED2_red = P1^5;
sbit LED2_green = P1^6;
sbit LED2_yellow = P1^7;
// 按键位定义
sbit key_auto = P3^0; // 自动
sbit key_step = P3^1; // 手动
sbit key_emerg = P3^2; // 紧急情况 110/120通过
sbit key_night = P3^6;// 夜间模式
uint cnt = 0; // 记录定时器定时了多少毫秒
uint sec = 0; // 记录定时器计时了多少秒
uchar light_num = 0;
// 四位八段共阴极数码管数字显示编码
uchar code table[]={
//"0" "1" "2" "3"
0x3f,0x06,0x5b,0x4f,
//"4" "5" "6" "7"
0x66,0x6d,0x7d,0x07,
//"8" "9" "A" "B"
0x7f,0x6f,0x77,0x7c,
//"C" "D" "E" "F"
0x39,0x5e,0x79,0x71
};
uchar code light[]={
// 主G辅R 主G辅R 主Y辅R
0xdb, 0xde, 0xd7,
// 主R辅G 主R辅B 主R辅R
0xbd, 0xed, 0x7d,
0xdf, 0xee, 0xdd
};
/*************函数声明********************/
void delay_ms(uint);
void system_Init();
void Display_R_time(uchar);
void Display_C_time(uchar);
void key_scan();
void main()
{
system_Init();
while(1)
{
key_scan();
}
}
// 毫秒级延时
void delay_ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=123;y>0;y--);
}
// 系统初始化
void system_Init()
{
wela=0; // 关闭位选
dula=0; // 关闭段选
TMOD=0x01; // 定时器0方式1 16位
TH0=0x4c; // 定时器装初值 50ms(11.05926MHz TH0=0x4c TL0=0x00)
TL0=0x00; // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
EA=1; // 开总中断
ET0=1; // 开定时器0中断
TR0=1; // 允许中断溢出
}
// 显示横向的(即辅干道)倒计时
void Display_R_time(uchar time)
{
uchar time_tens, time_ones;
time_tens = time / 10; // 提取倒计时时间的十位数
time_ones = time % 10; // 提取倒计时时间的个位数
// 下面对两位数倒计时时间进行显示(数码管)
P0=0xff;
wela=1;
P0=0xbf;
wela=0;
dula=1;
P0=table[time_tens];
dula=0;
delay_ms(1);
P0=0xff;
wela=1;
P0=0x7f;
wela=0;
dula=1;
P0=table[time_ones];
dula=0;
delay_ms(1);
}
// 显示竖向的(即主干道)倒计时
void Display_C_time(uchar time)
{
uchar time_tens, time_ones;
time_tens = time / 10;
time_ones = time % 10;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
dula=1;
P0=table[time_tens];
dula=0;
delay_ms(1);
P0=0xff;
wela=1;
P0=0xf7;
wela=0;
dula=1;
P0=table[time_ones];
dula=0;
delay_ms(1);
}
void key_scan()
{
if(key_auto == 0)
{
delay_ms(5);
if(key_auto == 0) // 自动按钮按下
{
// 主干道通过 辅干道红灯
if(sec <= 15)
{
Display_C_time(15-sec); // 倒计时显示
Display_R_time(30-sec);
P1 = light[0]; // 主道绿灯亮 辅道红灯亮
}
else if(sec > 15 && sec <= 24)
{
Display_C_time(24-sec); // 倒计时显示
Display_R_time(30-sec);
P1 = light[1]; // 主道蓝灯亮 单独左转 辅道红灯亮
}
else if(sec > 24 && sec <= 30)
{
Display_C_time(30-sec); // 倒计时显示
Display_R_time(30-sec);
P1 = light[2]; // 主道黄灯亮 辅道红灯亮
}
// 下面换道
else if(sec > 30 && sec <= 35)
{
Display_R_time(35-sec); // 倒计时显示
Display_C_time(50-sec);
P1 = light[3]; // 主道红灯亮 辅道绿灯亮
}
else if(sec > 35 && sec <= 44)
{
Display_R_time(44-sec); // 倒计时显示
Display_C_time(50-sec);
P1 = light[4]; // 主道红灯亮 辅道蓝灯亮 单独左转信号
}
else if(sec > 44 && sec <= 50)
{
Display_R_time(50-sec); // 倒计时显示
Display_C_time(50-sec);
P1 = light[5]; // 主道红灯亮 辅道黄灯亮
}
else
{
sec = 0;// 秒数清零,继续循环上述代码
}
}
}
// 手动步进按钮按下,按一次,交通灯的状态改变一次
if(key_step == 0)
{
delay_ms(5);
if(key_step == 0)
{
if(light_num == 6)
{
light_num = 0;
}
P1 = light[light_num];
light_num++;
while(!key_step); // 松手检测
}
}
// 紧急情况 emergency
if(key_emerg == 0)
{
delay_ms(5);
if(key_emerg == 0)
{
P1 = 0xdd; // 主干道辅干道都是红灯
while(!key_emerg);
}
}
// 夜间模式
if (key_night == 0)
{
delay_ms(5);
if (key_night == 0)
{
P1 = 0x77; // 主干道辅干道都是黄灯
while (!key_night);
}
}
}
// 定时器0中断服务函数
void timer0() interrupt 1
{
TH0=0x4c; // 定时器装初值 50ms(11.05926MHz TH0=0x4c TL0=0x00)
TL0=0x00; // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
cnt++;
if(cnt == 20)
{
cnt = 0;
sec++; // 记录1秒
}
}