C51单片机 简单的交通红绿灯设计二

连同上文 C51单片机 简单的交通红绿灯设计一

设计二中选择使用定时器代替延时函数,定时器的介绍我找到一篇简单易懂的文章----C51的定时器_从入门到捕蛇者说的博客

延时函数与定时器的区别:延时函数会占据CPU的使用权,如果正在进行延时,其他动作需要等延时结束才能进行,而配置定时器可以打开中断函数,独立进行,不占据CPU。

总览一:数码管用来显示数字。

二:LED交通灯本质上就是二极管,含有红绿黄,作为交通灯。

三:配置计时器用以计时。(计时器的使用)

对于第二条,我本想用lcd1602显示屏做的,但...lcd1602在底层配置的时候应该是连动到了引脚,lcd1602显示的时候会干扰到二极管的亮灭,所以我还是用了前文的一个数码管。

#include <REGX51.H>
unsigned int count=0,led_count=0;
unsigned int Number;
sbit Green_Light = P1^5;
sbit Yellow_Light = P1^6;
sbit Red_Light = P1^7;
unsigned int i=0;
unsigned int x[23]={10,9,8,7,6,5,4,3,2,1,3,2,1,10,9,8,7,6,5,4,3,2,1};
void Timer0_init()
{
    TMOD = 0x01;
    TL0 = 0x00;
    TH0 = 0xDC;//定时器的初始化配置成10ms进入一次中断函数。
    TF0 = 0;
    TR0 = 1;//用以计时,当爆表后TF0会跳转为1(通过上述配置即10ms后TF0=1)
    ET0=1;
    EA=1;
    PT0=0;
}
void NiXie(unsigned char Number)
{
        switch(Number)
    {
        case 0:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=0;break;
        case 1:P0_1=P0_2=0;break;
        case 2:P0_0=P0_1=P0_3=P0_4=P0_6=0;break;
        case 3:P0_0=P0_1=P0_2=P0_3=P0_6=0;break;
        case 4:P0_1=P0_2=P0_5=P0_6=0;break;
        case 5:P0_0=P0_2=P0_3=P0_5=P0_6=0;break;
        case 6:P0_0=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
        case 7:P0_0=P0_1=P0_2=0;break;
        case 8:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
        case 9:P0_0=P0_1=P0_2=P0_3=P0_5=P0_6=0;break;
        case 10:P0_6=0;break;
    }
}
void main()
{
    Green_Light = 1,Red_Light = 1,Yellow_Light=1;
    Number = 10;
    Timer0_init();//初始化工作
    while(1)
    {}
}
Timer0() interrupt 1//TF0为一时执行终端函数,执行完后TF0自动归0
{
    TL0 = 0x00;
    TH0 = 0xDC;//再把初值设为9126,保证下次还能再进入中断函数,并且也用时10ms
    count++,led_count++;
    NiXie(x[i]);//数码管的闪烁,其实每个数字闪烁了100下,每次10ms。
    if(led_count >= 100)
    {
        P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=P0_7=1;//return
        i++;
        led_count = 0;
        if(i==23)
        {i=0;}
    }
    
    if(count>0&&count<1000)//0~第10秒
    {
        Green_Light = 0;
    }
    if(count>=1000&&count<1300)//第10秒~第13秒
    {
        Green_Light = 1;//关绿灯开黄灯
        Yellow_Light = 0;
    }
    if(count>=1300&&count<2300)//第13秒~第23秒
    {
        Yellow_Light = 1;//关黄灯开红灯
        Red_Light = 0;
    }
    if(count>=2300)
    {
        Red_Light = 1;
        count = 0;//一遍后归零
    }
}

机器周期 = 12 x 时钟周期 =12 x (1/时钟频率) 秒 = 12 / 时钟频率 秒 = 12 / 11059200 秒 = 12 000 000/ 11059200 微秒 = 1.085 微秒

配置十毫秒的计时:10ms需要数9216机器周期,你让它从65536-9126=56320(16进制表示为

0xDC00)开始数数

这样TL0=0x00;TH0=0xDC。

中断函数:与外部中断一样,定时器中断也有中断函数,同理,程序去执行中断函数就会把TF0的中断标志位自动清0,所以只要我们用了定时器中断函数,那么TF0就可以不用再出现在程序书写中了。

在代码中,我用了count和led_count分别计数,每次主函数跳转到中断函数后,用时10ms,每次count和led_count的值加一,进入一百次就是1秒钟。

如有不对的地方,非常期待您的指正。

实验现象:

猜你喜欢

转载自blog.csdn.net/qq_62262788/article/details/128600845