51单片机、动态数码管认识与编程

一、根据电路图实现动态数码管

1. 对于动态数码管

首先需要知道的是,动态数码管是一种对数码管的实现方式,并不是数码管的种类,静态数码管也是一种实现方式,所以说,静动态的数码管内部结构没有差异。

动态数码管常见于对多个数码管进行编程,采用扫描方式对各个数码管给源给码(源可以理解成电源,码可以理解成段码,段码即显示的内容),再通过单片机CPU的高速循环,使各个数码管得以同时呈现不同的数字。

2. 电路图

动态数码管电路图

可以看到,该8位数码管是通过J16给源,J12给码的方式来实现数码管的亮灭。电路图中,数码管将8个LED灯的引脚全部接到了J12口的八根线上,统一给码,再通过J16来控制。由于是共阴极数码管,故当J16对某一位给0时,该位对应的数码管则亮。

注:74573本身是个锁存器,但在这个电路中没有用到锁存功能,只是简单的当作功放来用,用来驱动发光管的功率放大。

3. 51 C编程

  • 这里使用P0口控制数码管的段码位,P2口控制数码管的COM口。
#include <reg51.h>

unsigned char screenNum[8]={1,3,5,7,2,4,6,8};

void printNum(int i,int state)
{
    //0123456789AbCDEF
    unsigned char num[16]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    if(state==0) P0=num[i];     //共阳
    else P0=~num[i];        //共阴
}
int main()
{
    unsigned char i;
    unsigned char j;
    while(1)
    {
        for(i=0;i<8;i++)
        {
            P2=~(1<<i);    // P2 接 J16 控制数码管的亮灭
            printNum(screenNum[i],1);    //显示数字
            j=8;
            while(j--) ;   //延时
            P0=0x0;        //消隐
        }
    }
    return 0;
}
  • 注意:【消隐操作】在送出第N+1位的段码前,一定要先把第N位的位段码关闭,不然第N+1位的段码会在第N位有个短暂的残留。这个短暂的残留影象就是残影了。
无消隐
消隐

二、配合38译码器实现动态数码管

1. 首先,什么是38译码器?

74HC138

38译码器有3个输入端口A、B、C和8个输出端口Y0~Y7。由输入端口控制输出端口的值。

2. 为什么使用38译码器?

使用38译码器来控制数码管的COM口可以节约IO口,其原理是:输入口的3位总共可以代表8个十进制数0-7,分别对应输出端口的8个引脚,使得38译码器实现以3个引脚控制八个输出端口,不过这样就造成8个端口无法同时被选中,一次只能选择一个端口,但是在实现动态数码管时可以使用它来控制COM口,因为在动态扫描过程中,要的就是一次只选择一个端口。

3. 3个输入端口如何控制8个输出端口?

查询74HC138芯片的数据手册,可找到芯片的译码表。

译码表

表中,Enable项已经初始化好了,我们只需要关心Select项中的A、B、C输入端口即可。

4. 编程

  • 这里使用P0口控制数码管的段码位,P2口控制数码管的COM口。
#include <reg51.h>

unsigned char screenNum[8]={1,3,5,7,2,4,6,8};
unsigned char placeArr[8]={0x0,0x01,0x02,0x03,0x04,0x05,0x06,0x07};

void printNum(int i,int state)
{
    //0123456789AbCDEF
    unsigned char num[16]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    if(state==0) P0=num[i];     //共阳
    else P0=~num[i];        //共阴
}
int main()
{
    unsigned char i;
    unsigned char j;
    while(1)
    {
        for(i=0;i<8;i++)
        {
            P2 = placeArr[i];
            printNum(screenNum[i],1);
            j=100;
            while(j--) ;    
            P0=0x0; 
        }
    }
    return 0;
}

5. 改进

考虑到控制38译码器只用到P2的P2.0、P2.1、P2.2三个引脚,其他引脚不应该去改动它们原本的值,故作以下改进:

  • 对P2.0、P2.1、P2.2三位清零,然后在循环中每次加一来改变其内的值。
  • 每扫描一排,则重新清零再次累加。
#include <reg51.h>

unsigned char screenNum[8]={1,3,5,7,2,4,6,8};

void printNum(int i,int state)
{
    //0123456789AbCDEF
    unsigned char num[16]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    if(state==0) P0=num[i];        //共阳
    else P0=~num[i];        //共阴
}
int main()
{
    unsigned char i;
    unsigned char j;
    while(1)
    {
        P2 &= 0xf8;
        for(i=0;i<8;i++)
        {
            printNum(screenNum[i],1);
            j=100;
            while(j--) ;    
            P0=0x0; 
            P2 += 1;    
        }
    }
    return 0;
}
  • 注意:需要将P2+=1放到消隐之后,原因是:P2从000开始,若加1后再显示则会发生错位。
最终显示

三、【实例】使用动态数码管实现倒计时

  • 接线与上图相同

1. 使用延时函数实现倒数间隔

#include <reg51.h>

unsigned char screenNum[8]={1,3,5,7,2,4,6,8};

void printNum(int i,int state)
{
    //0123456789AbCDEF
    unsigned char num[16]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    if(state==0) P0=num[i];        //共阳
    else P0=~num[i];        //共阴
}

int main()
{
    unsigned char i;
    unsigned char j;
    unsigned long count=10000;
    unsigned int timeCount=0;
    while(1)
    {
        unsigned long temp=count;
        for(i=0;i<8;i++)
        {
            screenNum[7-i]=temp%10;
            temp/=10;
        }
        P2 &= 0xf8;
        for(i=0;i<8;i++)
        {
            printNum(screenNum[i],1);
            j=100;
            while(j--) ;    
            P0=0x0; 
            P2 += 1;    
        }
        delay_ms(100);
        count--;
    }
    return 0;
}

烧录后发现,数字变化时会闪烁。

经分析,应该是延时函数导致的,因为动态数码管需要不断扫描数码管,如果存在延时函数则会中断数字的显示。

改进后使用一个计数器来实现近似延时,见2.

2. 使用计数器实现倒数间隔

#include <reg51.h>

unsigned char screenNum[8]={0,0,0,0,0,0,0,0};

void printNum(int i,int state)
{
    //0123456789AbCDEF
    unsigned char num[16]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
    if(state==0) P0=num[i];        //共阳
    else P0=~num[i];        //共阴
}

int main()
{
    unsigned char i;
    unsigned char j;
    unsigned long count=10000;
    unsigned int timeCount=0;
    while(1)
    {
        unsigned long temp=count;
        if(timeCount++>100)
        {
            for(i=0;i<8;i++)
            {
                screenNum[7-i]=temp%10;
                temp/=10;
            }
            timeCount=0;
            count--;
        }
        //P2接38译码器控制数码管COM口
        P2 &= 0xf8;      //P2.0-2置0
        for(i=0;i<8;i++)
        {
            printNum(screenNum[i],1);
            j=100;
            while(j--) ;      //延时
            P0=0x0; //消隐
            P2 += 1;     
        }
    }
    return 0;
}

这里还有两个问题:
①数字变化间隔不为真正的一秒
②数字变化时会轻微闪烁

待解决。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容