51单片机数码管动态扫描不用延迟不用定时器照样没有余辉


  最近在学习51单片机,学到A/D转换的时候,想用数码管显示数值,数码管之前就学过,那时个按照书上说的用延迟解决全速跑出现余辉的问题,书上没有说为什么全速跑会出现余辉,当时也没太在意思这个问题。而现在,再重新写数码管程序时发现了这个余辉,原来这个余辉一直存在,延迟并没有真正解决余辉,原来,书上给出的显示部分根本就不正确,下面的代码的显示部分才是正确的。

/*************************************************
File: NixieWithoutDalay.c
Description: 
    数码管动态扫描,全速扫描,不用延迟,没有余辉,书上
    说不用延迟会有余辉却没说为什么,现在才知道是因
    为显示部分没写对
*************************************************/
#include 
#include 

/* 八段数码管,显示1~8 */
#define START_NUM 1
#define END_NUM 8

/* JC-51A开发板上的段选和位选 */
sbit duan = P2^6;
sbit wei = P2^7;

/* 八段共阳数码管数字 */
unsigned char code gNumeric[10] = 
{
    0xC0, 0xF9, 0xA4, 0xB0, 0x99,
    0x92, 0x82, 0xF8, 0x80, 0x90
};

/*************************************************
Function: showNumeric
Description: 在数码管上显示一个数字 
Input: 
numeric, 要显示的数字,范围 0~9
pos, 要显示的位置,0x01显示在第一位,0x04显示在第三位
*************************************************/
void showNumeric(char numeric, char pos)
{
    // 这三行很重要,先把位选关掉,让所有数码管都灭,不然会有余辉
    // 而且这个余辉不容易发现
    P0 = 0x00; 
    wei = 1;
    wei = 0;
    
    P0 = gNumeric[numeric];
    duan = 1;
    duan = 0;
    
    P0 = pos;
    wei = 1;
    wei = 0;
}

void main()
{
    char num = START_NUM; 
    char pos = 0x01;
    while (1)
    {
        showNumeric(num, pos);
        ++num;
        if (END_NUM < num)
        {
            num = START_NUM;
        }
        pos = _crol_(pos, 1);
    }
}

这个代码是全速扫描的,不用延迟,不用定时器,没有余辉。

下面是运行效果:

这个余辉是怎么发现的呢?

请看下面几个图。

红框部分有余辉,余辉显示的是3。 余辉显示的是5。

发现了没有,这个余辉很有规律,总是在前面一位显示,而且显示的数字是挨着的那个。这个余辉最后是通过showNumeric函数里的前三行解决的。