要想让数码管显示更多的内容,一种方式是增加数码管的个数,但这样会带来成本的增加和体积的增大;另一种可行的方案是让数码管滚动显示,写一个滚动显示的数码管并不复杂,下面将使用stc89c52rc单片机和开发板配套的8位数码管写一个可以让数码管滚动显示的代码。

硬件连接

5baa1ed6a3eb3

如图,这是八个八段共阴数码管,意味着高电平点亮,数码管的段显通过74HC573连接到单片机P1口

74HC573是一个锁存器,当LE处于高电平的时候,输入和输出的信号是同步的,用在数码管主要用来增大驱动能力。

5baa230327c96

数码管的位显通过138译码器连接到单片机的P0口

138译码器通过3位的输入控制8位输出

代码编写

首先让数码管可以动态刷新显示

只要让对应段显点亮就可以了

下面是通过数码管的数据手册写出来的真值表,为了方便后面的显示,这里使用宏定义的方式定义真值表。

#define MAXWEI 8 //这里定义的是数码管的个数


#define E0 0x3f
#define E1 0x06
#define E2 0x5b
#define E3 0x4f
#define E4 0x66
#define E5 0x6d
#define E6 0x7d
#define E7 0x07
#define E8 0x7f
#define E9 0x6f
#define EE 0x00 //什么都不显示

定义一个数组用于存放要显示的数字

unsigned char Num[] = {
    E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,
    EE,EE,EE,EE,EE,EE,EE,EE,EE,EE

};

在main函数里面刷新显示


void main()
{
    unsigned char i = 0;

    while(1)
    {

        for(i=0;i<MAXWEI;i++)
        {

            P0 = i;
            P1=Num[i];
        }

    }
}

实际显示效果并不好

5baa29c28906d

这是因为显示刷新太快,数码管有残影导致的,为了解决这个问题,可以通过添加延时函数解决

void Delay1ms()        //@11.0592MHz
{
    unsigned char i, j;

    _nop_();
    i = 2;
    j = 190;
    do
    {
        while (--j);
    } while (--i);
}

void delay(unsigned int ms)
{
    while(ms)
    {
        ms--;
        Delay1ms();
    }

}

在主函数显示部分添加延时函数

void main()
{
    unsigned char i = 0;

    while(1)
    {
        for(i=0;i<MAXWEI;i++)
        {
            delay(1);
            P0 = i;
            P1=Num[i];
        }
    }
}

显示效果有明显改进

5baa2b5a435e5

接下来添加一些代码可以让它滚动显示

为了让代码滚动显示,只要在每次刷新完一次将显示的起使位置向后移一位,并在达到最后一个数码管后重新将显示起使位置切换到第一个。

开启一个定时器,在中断函数中将标志位后移。定时器最大只能开启50ms中断,所以添加标志位延长时间。

添加两个标志位,一个用于后移显示,另一个用于时间标志位

unsigned char j = 0;//后移显示
unsigned int a = 0;//时间标志

定时器初始化

void Timer0Init(void)        //500微秒@11.0592MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
    TMOD &= 0xF0;        //设置定时器模式
    TL0 = 0x00;        //设置定时初值
    TH0 = 0x4C;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0 = 1;
}

定时器中断函数

void tm0_isr() interrupt 1 
{
    TL0 = 0x00;     //设置定时初值
    TH0 = 0x4C;     //设置定时初值
    TF0 = 0;        //清除TF0标志
    a++;
    if(a==150)
    {
        j++;
        if(j==20)
        {
            j=0;
        }
    a=0;
    }      

}

在主函数中初始化定时器、开启中断,并使用后移标志。

void main()
{
    unsigned char i = 0;

    EA = 1;
    Timer0Init();
    while(1)
    {
        for(i=0;i<MAXWEI;i++)
        {
            delay(1);
            P0 = i;
            P1=Num[i+j];
        }
    }
}

并更改显示内容,适配滚动显示

unsigned char Num[] = {
      EE,EE,EE,EE,EE,EE,EE,EE,EE,
    E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,
    EE,EE,EE,EE,EE,EE,EE,EE,EE,EE

};

5baa33d76257f

额外的说明

滚动显示本质上还是八个数字逐个刷新,所以定义显示内容的数组里面存放了一些不显示的真值,这也是为什么数组长度是29而中断中让标志位等于20后就归零了。