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

这篇博文,将对数码管进行介绍和驱动,与之所关联的芯片,亦是前面所讲的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重新置零,再让数码管从第一位开始扫描至最后一位,以此类推……

}

由上可见,每次通过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~3位分别显示“0、1、3”,第四位熄灭,第5~8位分别显示“4、5、6、7”。
而静态数码管,一般用的很少,它的存在只是为了引出动态数码管。对于它的操作,那需要把位选全部选中,再控制段选即可。当然,这样下来我们也不需要“消影”的处理了。

未完待续……

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值