单片机可以连的显示外设有很多种,我们常用到的就是连接LED显示,但是除了LED以外,我们还有很多外部的显示元件,包括数码管、点阵屏等由圆管或者方管LED组成的显示屏,接下来我们着重来看如何使用51单片机外接数码管进行显示。
目录
数码管物理结构
编程点亮数码管
数码管静态 / 动态显示
数码管我们以单联的和双联的为例子,而其它的数码管都是由双联相同原理扩展即可。
首先来看单联,一个数码管由8个LED组成,它们包括组成一个“8”字型的7个LED和1个位于右下角的“ . ”点号LED,所以一共有8给LED。其中前面7个分为序号a~g,点为dp,控制这8个口会伸出8个引脚,但是注意到下图的话我们会发现其实还会多出两个引脚com。而对于单联LED数码管这两个引脚在内部会汇总到一起形成一条线上,这两个COM引脚统一接一种电位,作为公共端,然后再根据各伸出去的引脚a~g和dp来输入不同的电位以实现对数码管的控制。一般来说根据公共端接的是二极管的阳极还是阴极我们就可以判断该数码管是共阳极还是共阴极型数码管。
而对于双联LED的数码管就不同了,它的结构如下图所示。可以看到,它的LED有两个公共的COM端,而它各个数码管的a~g和dp引脚都是连到一个数码管上面。其实更多的多联LED数码管的连接方式也是类似:几个LED数码管就有几个公共COM端,而它们的单独引脚a~g和dp引脚都是统一连到一个数码管上。
看到这就很容易有疑问了,既然每一个数码管的a~g和dp引脚都连到一个数码管上面,那么我们平时使用到的假如四联LED数码管是怎么同时显示不同的四个数字的呢?其实这里用到了视觉残留的原理,其实我们每一次都是在动态点亮一个数码管!假如我们想要让四联LED数码管显示数字1234,那么在时刻1我会让第一个数码管的COM引脚导通,其它的数码管COM引脚接反电位,然后通过a~g和dp引脚输入数字1的显示信号让数码管显示数字1;再下一时刻2我会让第二个数码管的COM引脚导通,其它数码管的COM引脚接反电位,然后再向a~g和dp引脚输入数字2的显示信号让数码管显示数字2,以此类推...让四个LED数码管都快速显示一遍,而由于四个LED数码管显示的速度太快了,所以我们人眼是分辨不出在一个短暂的瞬间哪个数码管在亮,在我们看来是他们四个同时在亮!
⭐数码管内部的LED要接限流保护电阻吗?
因为数码管内部还是由LED组成,所以限流电阻是不可或缺的!外接5V电压时一般选择的限流电阻是在150Ω-700Ω左右。
接下来我们来细看一下数码管的共阴极和共阳极的意义。数码管的共阴极和共阳极是由COM公共接口接的是数码管内部LED的阳极还是阴极决定,如果COM接的是内部LED的阳极,那么该数码管就被称为共阳极数码管,而如果COM接的是内部LED的阴极,那么该数码管就被称为是共阴极数码管。共阳极数码管的COM端接的是高电平,它的a~g和dp引脚接的是低电平会点亮;而共阴极数码管的COM端接的是低电平,当它的a~g和dp引脚接的是高电平时会点亮。
我们先来看如何使用软件编程点亮一个数码管,下面是一个简单的代码:
ORG 00H
AJMP MAIN
ORG 30H
MAIN:
MOV P0, #92H
AJMP MAIN
END
其对应的测试结果:
其实对于我们使用编程方式来点亮数码管来说,如果数码管的位a~g对应单片机输出引脚px1~px7,那么我们会有一个单片机并口16进制状态对应的数码管显示的编码表:
数码管显示字符 | 共阴极引脚输出 | 共阳极引脚输出 |
0 | 3FH | C0H |
1 | 06H | F9H |
2 | 5BH | A4H |
3 | 4FH | B0H |
4 | 66H | 99H |
5 | 6DH | 92H |
6 | 7DH | 82H |
7 | 07H | F8H |
8 | 7FH | 80H |
9 | 6FH | 90H |
但是我们点亮数码管往往采用的不是这种方式,我们一般会在单片机里面找个位置制作一个表,这个表就存储着不同的数字显示信息。例如下面的例子是让数码管显示从0-9循环显示的代码(老师课件上的例子):
ORG 0000H
LJMP START
ORG 0030H
START: MOV DPTR, #TABLE
FUNC1: MOV A, #00H
MOVC A, @A+DPTR
CJNE A, #01H, FUNC2
SJMP START
FUNC2: MOV P0, A
LCALL DELAY
INC DPTR
SJMP FUNC1
DELAY: MOV R5, #20
D2: MOV R6, #20
D1: MOV R7, #248
DJNZ R7, $
DJNZ R6, D1
DJNZ R5, D2
RET
TABLE: DB 0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H, 80H, 90H
DB 01H
END
分析代码可以看出代码大概的思路,我们从下面看起,首先是下面的一个表,这个表中放的是让共阳极数码管显示从0-9的对应输出引脚的16进制状态码,它还有一个表尾值是01H,用来判断是否已经到达表尾。这个表可以方便我们找出数码管要显示的数值对应的段码,直接地址定位。
TABLE: DB 0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H, 80H, 90H
DB 01H
END
然后就是一个普通的延迟函数:
DELAY: MOV R5, #20
D2: MOV R6, #20
D1: MOV R7, #248
DJNZ R7, $
DJNZ R6, D1
DJNZ R5, D2
RET
接下来我们从头看起:前面程序定位置和跳转就不看了,从START开始看起。START函数一进来我们就将表的地址赋给DPTR,也就是说DPTR此时指向表头。然后进入FUNC1,把A+DPTR的值赋给累加器A,实际上就是DPTR的值(因为A是00H),因为CJNE比较的操作数是累加器A所以我们采用A来代替DPTR。然后判断A是否到达表尾01H,如果没有到达则跳转到FUNC2里面将此时DPTR(A)指向的表里的数据输出到数码管中显示,显示完后让DPTR自增指向表中的下一个数据,以此实现对表中每一个数据的遍历。当DPTR指向表尾01H时,程序不会从FUNC1进入FUNC2,而回从来一遍,即重新实现一次0-9的过程。
ORG 0000H
LJMP START
ORG 0030H
START: MOV DPTR, #TABLE
FUNC1: MOV A, #00H
MOVC A, @A+DPTR
CJNE A, #01H, FUNC2
SJMP START
FUNC2: MOV P0, A
LCALL DELAY
INC DPTR
SJMP FUNC1
输出结果:
数码管静态显示就是将数码管要显示的数值提早确定,然后单片机通过IO口将显示信息输出给数码管,然后利用锁存器(CD4511)与输出相连实现将显示字符锁存起来。这种方式只适用于少量数码管的不变化显示,其具有对IO口资源要求大、显示数值无法变化等缺点。
而我们平时常用到的是动态显示:该显示方式就是我们一开始提到的以人眼残留效应为原理的显示方式(但是下面的例子当时的参数设置不好,导致闪的很慢,看起来就是一个个闪的,应该将延迟函数的参数设置得小一点!)。这种显示方式中无论有多少个数码管都只需要8个IO口进行输出,因为它们公用a~g和dp引脚,变化的是COM引脚的状态。我们通过改变这8给引脚的状态输出不同的数值信息,然后通过改变不同的数码管的COM引脚状态来决定哪个数码管接收该信息。
下面我们来编程实现一下动态显示,不难看出,动态显示和前面循环点亮的区别就是动态显示是数据在多个数码管之间选择,而我们之前是只用一个数码管输出。
ORG 0000H
LJMP START
ORG 0030H
START: MOV DPTR, #TABLE
MOV R1, #7FH
FUNC1: MOV A, #00H
MOVC A, @A+DPTR
CJNE A, #01H, FUNC2
SJMP START
FUNC2: MOV B, A
MOV A, R1
RL A
MOV P2, A
MOV R1, A
MOV P0, B
LCALL DELAY
INC DPTR
SJMP FUNC1
DELAY: MOV R5, #20
D2: MOV R6, #20
D1: MOV R7, #248
DJNZ R7, $
DJNZ R6, D1
DJNZ R5, D2
RET
TABLE: DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H
DB 01H
END
输出结果:
图片来源及参考资料:
老师上课的课件
科普:LED数码管的驱动原理介绍 (360doc.com)