赞
踩
数码管是一种常用的显示设备,他有着价格便宜、使用简单的特点,在各个领域被广泛的应用,如空调、电子万年历、冰箱等等。学习数码管相关的编程之前,我们有必要了解一下数码管的一些概念和操作方式。
数码管也称LED数码管(LED Segment Displays),其是由多个发光二极管封装在一起组成。
常用的数码管有七段数码管和八段数码管,如下图所示。7段数码管由七个条状发光二极管组成,8段数码管由七个条状和一个点状发光二极管,即8段数码管比7段数码管多一个发光二极管单元(多一个小数点)。如果需要显示带小数的数据,应选用8段数码管。开发板上使用的是8段数码管。
图1:8段数码管比7段数码管
数码管按能显示多少个“8”可分为1位、2位、4位等数码管,如下图所示。开发板上使用的是8位数码管。
图2:数码管
数码管按发光二极管单元连接方式分为共阴极数码管和共阳极数码管,如下图所示。
图3:共阳极和共阴极数码管
一般地,操作数码管时,先执行段选再执行位选。位选是选择待操作的数码管,如开发板上的是8位数码管,位选就是选择8位数码管中的某一个。段选是选择数码管里面的LED灯,即通过选择点亮响应的LED灯以达到显示需要的数据的目的。
数码管的段码指的是数码管在显示不同的数据时,段选信号对应的二进制数据。下图是以8段共阴极数码管显示数字7为例来描述段码。
图4:共阴极数码管显示数字7时的段码
对于共阴极数码管来说,段的正极为高电平“逻辑1”时,段点亮,段的正极为低电平“逻辑0”时,段熄灭。如要显示数字“7”,需要点亮段A、段B和段C,8个段的负极对应的二进制数据为11100000,换算成16进制即为0xE0。如果是共阳极数码管,正好和共阴极数码管相反,8个段的正极对应的二进制数据为00000111,换算成16进制即为0x07。
由此,我们即可得出共阴极数码管显示的段码表,如下表所示。
表1:共阴极数码管显示的段码表
字形 | A | B | C | D | E | F | G | DP | 段码(共阴) |
0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | FC H |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 60 H |
2 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | DA H |
3 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | F2 H |
4 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 66 H |
5 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | B6 H |
6 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | BE H |
7 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | E0 H |
8 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | FE H |
9 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | F6 H |
A | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | EE H |
B | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 3E H |
C | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 9C H |
D | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 7A H |
E | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 9E H |
F | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 8E H |
小数点 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 01 H |
不显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00 H |
数码管的驱动显示方式有多种,大致可分为动态显示和静态显示。
动态显示其实就是利用LED的余辉效应和人眼的视觉暂留效应来实现的。动态显示方式外围驱动电路相对简单,占用单片机I/O较少,但是需要不断刷新数码管显示,因此,占用CPU时间较长。
静态显示是单片机发送数据之后,数据如何稳定有效的显示由外围锁存器件实现,这样可以大幅降低占用CPU的时间,但他会占用更多的I/O,并且外围驱动电路也相对复杂。
IK-64D4开发板上设计了8位共阴极数码管显示电路,该显示电路中使用74HC138译码器实现数码管的位选,74HC595芯片实现数码管的段选,电图原理图如下。
图5:数码管显示电路
数码管显示电路占用的STC8A8K64D4的引脚如下表:
表2:引脚分配
名称 | 引脚 | 说明 |
SCK | P3.2 | 和显示屏接口共用 |
SI | P3.4 | 和显示屏接口共用 |
RCK | P3.5 | 和显示屏接口共用 |
A0 | P4.0 | 和显示屏接口共用 |
A1 | P5.5 | 和显示屏接口共用 |
A2 | P4.4 | 和显示屏接口共用 |
数码管的段选是通过74HC595芯片实现的,74HC595是一个8位串行输入、并行输出的位移缓存器。数码管显示电路中,为了节省GPIO,74HC595的使能控制端在硬件上设置为恒有效(/OE连接到GND,恒为低电平)。74HC595的Q0~Q7 八位数据并行输出端并接到8个数码管的段选信号线上,这样,使用3个GPIO就可以向数码管发送段选信号。这3个GPIO各自的作用如下表所示。
表3:74HC595驱动信号
GPIO | 连接(74HC595) | 描述 |
P3.4 | SI | 发送串行数码管段选数据,经74HC595转为8位并行数据向数码管提供段选信号。 |
P3.2 | SCK | 产生数据移位时钟,上升沿时数据寄存器的数据移位,Q0→Q1→Q2→Q3→...→Q7,下降沿移位寄存器数据不变。 |
P3.5 | RCK | 产生数据锁存时钟,上升沿时将8 位锁存移位寄存器中的状态值并行输出,下降沿时存储寄存器数据不变。 |
传输段码时,单片机的P3.4输出8位串行段码数据,每传输一个数据位,P3.2产生一个上升沿时钟将数据移位,8个上升沿移位时钟后,8位段码数据传输完成,之后,P3.5产生一个上升沿,段码数据并行输出,由此,完成数码管的段选。
数码管显示电路使用74HC138译码器产生位选信号,同样,为了节省GPIO,74HC138的使能控制端在硬件上均设置为恒有效(E1、E2连接GND,恒为低电平;E3连接VCC,恒为高电平)。因此,程序中操作数码管时只需控制三个地址数据输入端(A0、A1、A2)去选中8个数码管中的待操作的数码管即可。
三个地址数据输入端(A0、A1、A2)是如何选中8个数码管中的一个的,这就要看74HC138译码器的真值表了(74HC138译码器的真值表如下图所示)。
H:高电平 L:低电平 X:任意电平
图6:74HC138真值表
由74HC138译码器的真值表可以看出,当74HC138使能后,A0、A1、A2的输入电平决定了Y0~Y7的输出(低电平有效),而且从Y0到Y7是和A2、A1、A0的值对应的,因此,当我们需要Y0~Y7中某个输出端输出低电平时,输入端A2、A1、A0输入对应的数值即可,如需要Y1输出低电平,则A2、A1、A0输入为001(16进制:0x01)即可。电路中的8个数码管是共阴极数码管,8个数码管的公共端依次连接到了Y7~Y0,由此,通过A0、A1、A2的“逻辑值”即可完成对待操作的数码管的位选。
对于数码管动态显示来说,主要考虑的有两个方面:数码管刷新和显示数据更新。
数码管动态显示驱动程序设计的方法很多,下面是一种基于定时器刷新的方法,供读者借鉴。
数码管驱动程序原理如下图所示,定义一个数组,该数组共有8个元素,分别用于保存8位数码管的段码,即数组中第1个元素用于保存8位数码管中第1位数码管的段码,第2个元素用于保存第2位数码管的段码,以此类推。
使用一个定时器用于刷新数码管显示,在定时器中断服务函数中从数组中取数码管的段码,完成对数码管显示的刷新。这样,当我们需要修改数码管显示内容时,只需要修改数组中的段码即可。
图7:数码管软件驱动原理
定时器刷新数码管显示的流程图如下,每次进入定时器中断服务函数后刷新8位数码管中的一位。这里,定义一个变量“ledseg_nod”用于记录数码管的位,每次刷新后“ledseg_nod”加1,到达8时,表示8位数码管全部刷新,“ledseg_nod”的值设置为0,开始新一轮刷新。
图8:定时器刷新数码管流程
通过4个轻触按键KEY1~KEY4控制数码管显示内容,KEY1控制第1个和第2个数码管,KEY2控制第3个和第4个数码管,KEY3控制第5个和第6个数码管,KEY4控制第7个和第8个数码管。
程序复位运行后,8个数码管全部显示数字0,每按动一次按键,该按键控制的数码管显示内容加1,加到F后再次按动按键返回数字0,如此反复。
因为在“main.c”文件中使用了“ledseg.c”文件中的函数,所以需要引用下面的头文件“ledseg.h”。
代码清单:引用头文件
数码管常用来显示数字“0~9”和字符“A~F”,他们的段码定义如下:
代码清单:段码表
定义一个名称为“SEG8_DispArray”的数组,用于存放8个数码管显示的段码,初始化值均设置为数字“0”的段码“0xFC”,数码管刷新时从该数组读取段码,代码清单如下。
代码清单: 8位数码管段码存放数组
数码管初始化主要包括引脚配置和数码管初始显示状态的设置,代码清单如下。这里要注意的是,如果需要改动数码管初始显示内容,修改数组SEG8_DispArray中的值即可,默认值是显示数字“0”。
代码清单:数码管初始化
为了程序中操作方便,我们先用宏定义对8位数码管中的各个位进行编号,让数码管和数组“SEG8_DispArray”关联。这里要注意一下,开发板为了布线方便,8位数码管是反序连接到74HC138的输出“Y0~Y7”的。
代码清单:数码管位定义
程序中先发送段码信号,8位串行段码经过74HC595后并行输出完成数码管的段选,之后发送位选信号,点亮数码管,代码清单如下。
代码清单:发送段选和位选信号
发送位选信号的函数代码清单如下。
代码清单:发送位选信号函数
本例中使用Timer2刷新数码管,Timer2定时时间配置为2ms,每次中断刷新一位数码管。程序中使用变量“ledseg_nod”记录数码管的位,8位数码管一轮刷新完成后,“ledseg_nod”复位(值设置为0),进入新一轮的刷新,代码清单如下。
代码清单:定时器2中断服务函数中刷新数码管
主函数中完成相关的初始化之后,在主循环里面调用按键扫描函数buttons_scan()查询是否有按键按下,如果有按键按下则更新数码管显示内容,代码清单如下。
代码清单:主函数
按照下图所示短接跳线帽,因为数码管和显示屏复用了GPIO,因此,使用数码管时不能安装显示屏。
图9:跳线帽短接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。