程序说明
- 文件名:main.c
- 描 述:实现交通信号灯,按键K2实现选择灭零
- 版本号:v1.0.0
- 型 号:KST-51
程序演示
程序代码
#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY2 = P2^5;
unsigned char code LedChar[] = { //数码管显示字符转换表
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[3] = { //显示缓冲区,前两个初值0xFF确保启动时数码管都不亮,第三个为0x3F确保启动时二极管显示为绿灯
0xFF, 0xFF, 0x3F
};
unsigned char i = 0; //动态扫描的索引
unsigned int cnt = 0; //记录T0中断次数
unsigned char flag1s = 0; //1秒定时标志
unsigned char keyflag = 0; //按键判断标志默认为0
unsigned char backup = 1; //用于记录按键的值
unsigned int time = 0; //用于延时
void main()
{
unsigned long sec = 9; //起始秒数秒数
unsigned char color = 1; //颜色索引:0-绿色/1-黄色/2-红色,启动时为绿灯,下一个状态为黄灯,故这里为1黄灯
EA = 1; //使能总中断
ENLED = 0; //使能U3,选择控制数码管
ADDR3 = 1; //因为需要动态改变ADDR0-2的值,所以不需要再初始化了
TMOD = 0x01; //设置T0为模式1
TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms
TL0 = 0x67;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
P2 = 0xF7;
while (1)
{
if(KEY2 != backup) //比较当前值与前次值不相等说明此时按键有动作
{
if(backup == 0)
{
keyflag = !keyflag; //每按一次"keyflag"取一次反
}
backup = KEY2; //更新备份为当前值,以备进行下次比较
}
if (flag1s == 1) //判断1秒定时标志
{
flag1s = 0; //1秒定时标志清零
if(sec == 0) //秒计数自减1
{
switch (color) //LED8/9代表绿灯,LED5/6代表黄灯,LED2/3代表红灯
{
case 0: //切换到绿色,亮60秒
color = 1;
sec = 9;
LedBuff[2] = 0x3F;
break;
case 1: //切换到黄色,亮3秒
color = 2;
sec = 2;
LedBuff[2] = 0xE7;
break;
case 2: //切换到红色,亮60秒
color = 0;
sec = 9;
LedBuff[2] = 0xFC;
break;
default: break;
}
}
else
{
sec--;
}
}
//以下代码将sec按十进制位从低到高依次提取并转为数码管显示字符
LedBuff[0] = LedChar[sec%10];
//如果此时sec十位为0当按键标志为1时 输出0xFF,关闭数码管显示,使其实现灭零效果
if(sec/10%10 == 0 && keyflag == 1)
{
LedBuff[1] = 0xFF;
}
else
{
LedBuff[1] = LedChar[sec/10%10];
}
}
}
/* 定时器0中断服务函数 */
void InterruptTimer0() interrupt 1
{
TH0 = 0xFC; //重新加载初值
TL0 = 0x67;
cnt++; //中断次数计数值加1
if (cnt >= 1000) //中断1000次即1秒
{
cnt = 0; //清零计数值以重新开始下1秒计时
flag1s = 1; //设置1秒定时标志为1
}
//以下代码完成动态扫描刷新
P0 = 0xFF; //显示消隐
switch (i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break; //倒计时显示个位
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break; //倒计时显示十位
case 2: ADDR2=1; ADDR1=1; ADDR0=0; i = 0; P0=LedBuff[2]; break; //红绿灯显示位
default: break;
}
}