/*
* 人行道交通灯程序:LED2(红灯)、LED3(黄灯)、LED4(绿灯)
* 红灯30秒,绿灯3秒,绿灯15秒,倒计时
灯亮时间显示在数码管上
* 晶振11.0592MHz,LED、数码管由三八译码器控制,T0中断
*程序思路:由于三八译码器每次只能输出一个低电平,因此必须用动态扫描方式点亮数码管及LED,中断间隔1ms
*亮灯时间倒数,红灯60秒,绿灯20秒,黄灯3秒,顺序:红 - 绿 -黄 -红循环,因此每经历1000次中断,实现数字递减。
*/
#include<reg52.h>
unsigned char K;//1s定时标志
unsigned char SMG_BUFFER[2]={0xff,0xff};//数码管显示缓冲
unsigned char RED,YELLOW,GREEN;
sbit LED2_RED = P0^0; //红灯接口
sbit LED3_YELLOW = P0^1;//黄灯接口
sbit LED4_GREEN = P0^2; //绿灯接口
//三八译码器控制数码管,个位:01000,十位:01001
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED1 = P1^4;
//数码管0~9
unsigned char code SMG[10]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管显示
void SMG_DISPLAY()
{
unsigned char SHIJIAN;//灯亮时间
static unsigned char color = 0;//颜色标志:0:红灯,1:黄灯,2:绿灯 ,默认从红灯开始
if(SHIJIAN <= 1)//倒数到1秒时,开始变化,
{
switch(color)
{
case 0:color = 2;SHIJIAN = 60;RED = 1;break;//红灯60秒,结束后红转绿,红灯标志位置1
case 1:color = 0;SHIJIAN = 3;YELLOW = 1;break;//黄灯3秒,结束后黄转红,黄灯标志位置1
case 2:color = 1;SHIJIAN = 20;GREEN = 1;break;//;绿灯20秒,结束后绿转黄,绿灯标志位置1
default:break;
}
}
else SHIJIAN--; //时间递减
if(SHIJIAN == 1)//直到1,时间发生变化
{
RED = 0;YELLOW = 0; GREEN = 0;//各标志位置0
}
SMG_BUFFER[0] = SMG[SHIJIAN % 10];//数码管显示,个位
SMG_BUFFER[1] = SMG[SHIJIAN / 10 % 10]; //十位
}
//定时器配置
void config_interruptime0()
{
TMOD = TMOD & 0XF0;
TMOD = TMOD | 0X01;
TH0 = 0XFC;
TL0 = 0X66;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void init()
{
ADDR3 = 1;
ENLED1 = 0;
}
int main()
{
init();
config_interruptime0();
while(1)
{
if(K == 1)//检查1秒定时时间是否达到
{
K = 0;//K重置
SMG_DISPLAY();//刷新显示
}
}
return 0;
}
void interruptime0() interrupt 1
{
static unsigned int cnt = 0;
static unsigned int i = 0;
TH0 = 0XFC; //1ms初值
TL0 = 0X66;
cnt++;
switch(i)
{
case 0:P0 = 0XFF; ADDR0 = 0; ADDR1 = 0; ADDR2 = 0; i++; P0 = SMG_BUFFER[0];break;//数码管个位显示
case 1:P0 = 0XFF; ADDR0 = 1; ADDR1 = 0; ADDR2 = 0; i++; P0 = SMG_BUFFER[1];break;//数码管十位显示
case 2:P0 = 0XFF; ADDR0 = 0; ADDR1 = 1; ADDR2 = 1; i=0; //LED显示
if(RED == 1)
{
LED2_RED = 0;
}
if(YELLOW == 1)
{
LED3_YELLOW = 0;
}
if(GREEN == 1)
{
LED4_GREEN = 0;
}
break;
}
if(cnt == 1000)
{
K = 1;//1秒时间达到时,K = 1
cnt = 0;
}
}