单片机
返回首页

51单片机之外设——玩转数码管

2020-04-06 来源:eefocus

这篇博文,将对数码管进行介绍和驱动,与之所关联的芯片,亦是前面所讲的74HC138译码器、74HC02或非门、74HC573锁存器,所用的 I/O 口,依然是11个——P2.5P.6P2.7以及P0~P7。


首先,什么是数码管?


数码管是由多个发光二极管封装在一起,而组成的“8”字型元器件。一般开发板上所用到的是四位共阳极(或者共阴极)的数码管,也就是说,是将数码管四个四个的连在一起,并将引脚引出。下面附上四位一体的数码管以及单个数码管的原理图:

这里写图片描述这里写图片描述

其实物图如下所示:

这里写图片描述

可见,四位一体的数码管,只是将四个数码管封装在一起,同时将所有数码管的段选引脚一起引出,位选引脚仍然单独引出而已(什么是段选?位选?接下来会介绍)。


上面说到了共阳极,那自然会有共阴极吧?是的!那什么是共阳极和共阴极呢?让我们看看他们的内部原理图就一目了然了!

这里写图片描述

其中a,b,c,d,e,f,g,dp即为数码管中每个 LED 灯(共8个),COM口是位选端。单个数码管(一位数码管)的COM口有两个(可以起到分流以及让引脚分布均匀的作用,因为元器件的引脚分布多为偶数个)。


再来看下,数码管显示的工作状态:静态数码管和动态数码管。


静态数码管:当多位数码管连接在一起时,它们的“位选”是可单独控制的,但是他们的“段选”都是连接在一起的(比如说,我们控制四位数码管的“a”灯亮,假如我们位选是选择了四位,那么四个数码管的“a”灯都会亮)。所以当我们将所有的位选一起控制时的数码管显示的模式即为“静态数码管”,此时所有的数码管显示的值都相同。


动态数码管:数码管工作时,让数码管显示出来的数值不尽相同(意思就是,我们不把所有数码管的位选一起控制)。但是这里我们会想到,明明段选是在一起的,为什么会显示的不一样呢?这里我们利用数码管的余晖效果以及人眼视觉的暂时停留现象,使人们感觉各位数码管同时再显示。而实际上,我们每次单独对一位数码管操作,再给出段选,本质上是一位一位轮流显示的,只是速度十分快,我们看不出来而已。当然,假如时不时控制位选和段选,就会造成一起不清晰的现象——这样就是我们所说的“鬼影”。所以我们在使用数码管工作时,时常要注意的操作就是“消影”。意思是每次操作完一个数码管的位选和整个数码管的段选后,操作所有的数码管进行短暂的“熄灭”。这里在后面的代码会有有分析。


下面看一下,开发板上对应的数码管的原理图(所用的是共阳极数码管):

这里写图片描述
这里写图片描述

可见,我们仍是通过138和或非门,锁存器进行控制。其中箭头所指的是网络标号的连接处,锁存器输出端的“abcdefgdp”并不是直接连接数码管的段选的“abcdefgdp”。


下面,将数码管动态显示的部分代码给出:(P2口控制数码管位选和段选的选择,P0口负责往数码管送相应的位选和段选码)


#define unsigned char

//数码管的段码:0   1     2    3    4    5    6    7    8    9   消影

uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //用一个数组,存好数码管的十六进制段选编码

uchar dspbuf[]={10,10,10,10,10,10,10,10};   //

uchar dspcom = 0;


void display()

{

    P2 = (P2 & 0x1f)|0xE0;          //通过138,或非门,打开Y7C所在的锁存器,操作数码管的段选

    P0 = 0xff;                      //通过P0口给数码管送段码0xff,让数码管熄灭,也就是“消影”操作

    P2 &= 0x1f;                     //关闭段选锁存器


    P2 = (P2 & 0x1f)|0xC0;          //打开Y6C所在锁存器,操作数码管位选

    P0 = (1 << dspcom);             //通过P0口给数码管送位码,每次只选中一位数码管(共阳极数码管,给1是选中)

    P2 &= 0x1f;                     //关闭位选锁存器


    P2 = (P2 & 0x1f)|0xE0;          //打开段选锁存器

    P0 = tab[dspbuf[dspcom];        //通过P0给数码管送段码,具体数值由dspbuf[]数组而定

    P2 &= 0x1f;                     //关闭段选锁存器


    if(++dspcom == 8)

        dspcom = 0;               //上面的代码每次选中一位数码管,当display函数操作了7次之后,dspcom的值为8(每次先让dspbuf自加1,再与“8”做比较),若满足条件,则让dspcom重新置零,再让数码管从第一位开始扫描至最后一位,以此类推……


}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

由上可见,每次通过P0 = (1 << dscom)选中数码管一位,经过dspcom加1后,再选中下一位数码管(1左移dspcom位,1后面的二进制数都是0,例如 1 << 5,即为 0010 0000;1 << 2 ,即为 0000 0100)。

而一直以来未被操作的数码管(未被位选)的段码值一直默认为“tab[dspbuf[10]]”,也就是0xff(熄灭状态),这也是一开始就把dspbuf[]数组全部赋值为“10”的原因。

例如我们这样这样写:


void main()

{

    while(1)

    {

        dspbuf[0] = 1;

        dspbuf[1] = 2;

        dspbuf[2] = 3;

        dspbuf[3] = 10;  //其实也要我们未对第4位数码管进行操作,则其段码默认为tab[dspbuf[10]]

        dsobuf[4] = 4;

        dspbuf[5] = 5;

        dspbuf[6] = 6;

        dspbuf[7]  7;

        display();

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

则,以上现象便是让数码管第1~3位分别显示“0、1、3”,第四位熄灭,第5~8位分别显示“4、5、6、7”。

而静态数码管,一般用的很少,它的存在只是为了引出动态数码管。对于它的操作,那需要把位选全部选中,再控制段选即可。当然,这样下来我们也不需要“消影”的处理了。


未完待续……

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章