程序说明

  • 文件名: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;
    }
}
End

本文标题:红绿灯(按键K2实现选择灭零)

本文链接:http://www.kitteno.com/archives/trafficlights.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

最后修改:2022 年 04 月 24 日
如果觉得我的文章对你有用,请随意赞赏