基于单片机的数码管实验 八段数码管简介

8.1 八段数码管简介在我们生活中随处可见数码管的应用,数码管的应用形式多种多样,抛开事物表象,深入到它的本质,正所谓万变不离其中,数码管应用的原理都是基本相通的。本章我们将详细介绍数码管的基本原理以及数码管的应用。最典型的数码管为8段led数码管,外观如下图所示:
如上图所示,数码管包括a、b、c、d、e、f、g以及dp共8段,实际上8段为8个独立的led。上面8段led组成1位数码管。数码管按照内部连接方法的不同分为共阴型或共阳,当8段led的阴极连接在一起称为为共阴型,阳极连接在一起称为共阳型。如下图所示为4位共阳型的8 段数码管。
如上图所示,4位数码管每一位的8段led的阳极连在一起,组成共阳极型数码管,8段数码管的阴极分别连接在一起。当选中某一位的阳极使其为高电平,使8段数码管的阴极对应的位低电平便可点亮数码管。例如,dp、g、f、e、d、c、b、a电平值依次为:1、1、1、1、1、0、0、1时数码管显示为数字1。据此可以编辑共阳数码管的真值表,如下表所示:
一般点亮一段数码管需要至少10ma, 而单片机管脚输出的电流较小,无法驱动数码管,可以采用上拉电阻、三极管驱动或采用专用驱动芯片进行驱动。ry-51单片机开发板采用两个74hc573驱动芯片,驱动2个4位的数码管,共8位数码管如下图所示:
8.2 锁存器74hc573功能介绍如上图所示,u3,u4为8位的数据锁存器74hc573,d7-d0为数据输入端,q7-q0为与输入端一一对应的输出端。74hc573有2个控制信号分别为第1、11管脚、1管脚为芯片使能控制端,11管脚为数据锁存控制端。
当1接高电平时,芯片不工作,无论数据输入端为高、低电平,输出端q7-q0为高阻态。只有当1管脚为低电平时,芯片才能正常工作,如图8-3所示u3、u4均将1管脚直接接地。
在1管脚接地的情况下,当11管脚为高电平时,d7-d0输入为高电平时,q7-q0输出为高、同理当输入为低电平时,输出为低电平,此时相当于芯片的d7-d0与q7-q0是一一连通的。
当11管脚为低电平时,无论输入端d7-d0是高或者低电平,q7-q0保持原来的值不变。
利用上面的特点我们就可以实现数据的锁存了。假设我们要把0xfb锁存到q7-q0,首先使11管脚为高电平,给输入端d7-d0赋值0xfb,此时输出端q7-q0输出为0xfb,此时将11管脚拉为低电平并一直保持,那么此后无论输入端d7-d0为何值,q7-q0均为0xfb,因此完成了数据的锁存。74hc573真值表如下表所示:
如上面原理图所示,根据锁存器74hc573的特点,利用单片的一个8位端口,以及两个用于控制的i/o口便能控制8位数码管了。如图所示,输入数据d7-d0与单片的p0口相连,u3、u4的11管脚分别与单片机的i/o口p2.7、p2.6相连。锁存器u3的输出端q7~q0分别与数码管的a-g,dp相连,锁存器u4的输出端q7-q0分别与8位数码管的公共端相连。
8.3 单片机控制数码管下面我们通过举例来讲解数码管的控制过程,以使第5位数码管显示数字8为例。如表8-1所示数字8对应数码管真值为0x80,通过单片机的p0口将0x80锁存到u3的输出口。如图8-3所示,第5位数码管公共端we5对应的是锁存器u4的q4,应只需q4为高电平,q7-q5,q3-q1为低电平,便可使第5位数码管显示数字8,其它数码管不显示。因此通过单片机的p0口将0x10锁存到u4。数码管的显示总结如下,首先将字码锁存到u3,然后将数码管的显示位锁存到u4。数码管显示程序如下所示:
/*----------------------------------------------------** 数码管5显示数字8----------------------------------------------------*/#includesbit du = p2^7;sbit we = p2^6;void main(){ p0 = 0x80;//显示数字8 du = 1; du = 0; p0 = 0x10;//第5位数码管 we = 1; we = 0; while(1);}程序代码如上所示,在主程序中首先把数字8锁存到锁存器u3,然后将数码管5公共端的高电平锁存到u4,将程序编译并下载到单片机检验实际显示效果。每一个数字对应数码管都是固定的,在实际应用中每条语句中都对p0进行赋值的话会比较繁琐而且不便于程序阅读,我们往往将数码管的真值放在一个数组中,程序中调用数组即可,改进程序如下所示:
/*----------------------------------------------------** 数码管5显示数字8,字码组放入数组中----------------------------------------------------*/#include#define uchar unsigned char#define uint unsigned intsbit du = p2^7;sbit we = p2^6;//共阳型(0~9,a,b,c,d,e,f,全亮,全灭),字码组uchar code table_d[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00,0xff};//位选数组uchar code table_w[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0x00};void main(){ p0 = table_d[8];//显示数字8 du = 1; du = 0; p0 = table_w[4];//第5位数码管 we = 1; we = 0; while(1);}如代码所示,将数码管真值表放入数组table_d[],数组的第0位对应的数字为0,第8位对应的数字为8,因此,如代码所示,需要显示数字8,直接将table_d[8],赋值给p0即可,方便又好记。table_w[]设计的原理相同。将程序下载到开发板,显示效果与前面保持一致。
前面讲解的都是让某一个数码管显示某一个固定的值,下面我们讲解较为复杂一点数码管显示。例如,第1位数码管显示数字0,500ms之后第2位数码管显示数字1,直到第8位数码管显示7,然后循环上述步骤。要实现上面的功能我们需要用到前面讲解的定时器功能,即每500ms在定时器中断程序中给数码管更新一次数值。程序代码如下所示。
/*----------------------------------------------------** 数码管1~8循环显示数字0~7,间隔500ms** 定时器中断方式----------------------------------------------------*/#include#define uchar unsigned char#define uint unsigned int#define fosc 11059200 //单片机晶振频率#define t_1ms (65536 - fosc/12/1000) //定时器初始值计算uint count = 0;uint flag = 0;sbit du = p2^7;sbit we = p2^6;//共阳型(0~9,a,b,c,d,e,f,全亮,全灭),字码组uchar code table_d[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00,0xff};//位选数组uchar code table_w[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0x00};void main(){ tmod = 0x01; //定时器工作模式配置 tl0 = t_1ms; //装载初始值 th0 = t_1ms >>8; tr0 = 1; //启动定时器 et0 = 1; //允许定时器中断 ea = 1; //开总中断 while(1); //循环}void timer0() interrupt 1{ tl0 = t_1ms;//重装初始值 th0 = t_1ms >>8; count++; if(count >= 500)//每一毫秒进入一次中断,达到500次则为500ms,跟新一次数码管显示。 { count = 0; p0 = table_d[flag];//数字0~7循环 du = 1; du = 0; p0 = table_w[flag];//数码管1~8循环点亮 we = 1; we = 0; flag++; if(flag >=8) flag =0; }}将程序下载到单片机开发板检验效果是否与预期一致。
8.4动态显示数码管前面讲解的数码管显示均为在某个时间内只能显示一个数码管,那么如何让8个数码管同时显示不同的数。前面我们讲解的例子为数码管1到8分别显示数字1到8,显示的间隔时间为500ms,如果我们将时间间隔该为100ms,那么数码管切换的速度比以前快了5倍,当把间隔该为2ms时,由于间隔时间太短,感觉前一个数码管还没来的及完全熄灭,后面的数码管就点亮了,这就是人眼睛的视觉暂留效应。
因此,你可以看到数码管上同时显示了01234567共八个数,这就是动态数码管显示的原理。只需要将上面的程序稍加改动便可实现,将语句“if(count>=500)”改为“if(count>=2)”。将修改好的程序编译下载到开发板观察效果。
8.5 数码管消隐当把上面的程序下载到开发板时,8位数码管会同时显示“01234567”共8个数字。但是,细心的同学会发现,有的数码管不应该显示的段会有点亮,但亮度会比较低,看起来像阴影一样。这种现象是怎么形成的呢,又该怎么消除呢?下面我们通过程序来具体分析。
8.4节所讲的定时器中断程序如上图所示,根据前面介绍可知,每隔2ms语句51-59会执行一次,每次flag的值会加1。第一次时flag=0,数码管1显示数字0,第二次时,flag=1,数码管2显示数字1,如此循环下去。当第二次执行到第51行语句时,此时还没有选择数码管2,而是第一次执行语句57时选中了的数码管1,只有当语句执行到57时,才完成数码管2的选定,因此,在执行语句51-57期间,是数码管1显示了数字1,当执行到57之后的2ms时间内是数码管2显示了数字1。由于语句执行语句51-57的时间远小于2m,因此亮度较低,这就是我们上面观察到的阴影。阴影产生的原因找到了,下面我们讲解阴影的消除了。如果我们在语句51之前先把所有的数码关都关掉,就不会出现上述情况了。程序如下:
void timer0() interrupt 1{ tl0 = t_1ms;//重装初始值 th0 = t_1ms >>8; count++; if(count >= 2)//每一毫秒进入一次中断,达到2次则为2ms更新一次数码管。 { count = 0; p0 =table_w[9];//关闭所有数码管,消隐处理 we = 1; we = 0; p0 = table_d[flag];//数字0~7循环 du = 1; du = 0; p0 = table_w[flag];//数码管1~8循环点亮 we = 1; we = 0; flag++; if(flag >=8) flag =0; }}将程序重新编译,下载到开发板。正如程序设计所愿,数码管阴影成功被消除。
8.6 数码管应用这里我们在扩展一下数码管的应用,做一个简单秒表,在数码管上显示。程序设计原理如下:在定时器中断程序中增加一个变量t_count,当1ms进入一次定时器中断时自加一次,然后在主程序中判断是否达到了1000次即1s的时间,每秒钟变量sec自加1次,记录时间。将sec个、十、百、千位保存到数组buf_led[]中,在将数组显示到数码管上,程序如下所示:
/*----------------------------------------------------** 秒表----------------------------------------------------*/#include#define uchar unsigned char#define uint unsigned int#define fosc 11059200 //单片机晶振频率#define t_1ms (65536 - fosc/12/1000) //定时器初始值计算uint count = 0;uint flag = 0;uint t_count = 0;uint sec = 0;sbit du = p2^7;sbit we = p2^6; uchar buf_led[8] ={0};//共阳型(0~9,a,b,c,d,e,f,全亮,全灭),字码组uchar code table_d[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00,0xff};//位选数组uchar code table_w[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff,0x00};void main(){ tmod = 0x01; //定时器工作模式配置 tl0 = t_1ms; //装载初始值 th0 = t_1ms >>8; tr0 = 1; //启动定时器 et0 = 1; //允许定时器中断 ea = 1; //开总中断 while(1) //循环 { if(t_count >=1000) { t_count =0; sec++; buf_led[7]= sec%10; buf_led[6]= sec/10%10; buf_led[5]= sec/100%10; buf_led[4]= sec/1000%10; } }}void timer0() interrupt 1{ tl0 = t_1ms;//重装初始值 th0 = t_1ms >>8; t_count++; count++; if(count >= 2)//每一毫秒进入一次中断,达到2次则为2ms更新一次数码管。 { count = 0; p0 =table_w[9];//关闭所有数码管,消隐处理 we = 1; we = 0; p0 = table_d[buf_led[flag]];//显示秒 du = 1; du = 0; p0 = table_w[flag];//数码管1~8循环点亮 we = 1; we = 0; flag++; if(flag >=8) flag =0; }}8.7本章小结本章详细介绍了数码管的工作原理、锁存器74hc573的工作原理及使用。数码管的显示控制以数码管显示中的定时器应用。

凭什么联发科技MT8516能获奖?
创新不竭,探索不止 | 开发者说·DTalk 年中优秀赏
如何用万用表对IGBT进行引脚识别和检测
新增一起iPhone7起火爆炸事件,国内事故超十件
全球软件定义网络解决方案增长,2018年SDN市场上哪10种解决方案最受追捧?
基于单片机的数码管实验 八段数码管简介
高通骁龙870发布:7nm工艺
电脑芯片为什么短缺
GSMA正积极联系高通推动物联网发展
缺芯,真的只是源于一次误判吗?
可穿戴设备:始终确保工人安全
2021年人工智能数据采集标注行业的四大趋势
ToF传感器究竟有多神奇?
Life Technologies 推出新型DNA试剂盒
告别数字时代的汽车仪表该走向何方
PCB布局挑战——改进您的开关模式电源设计
热敏打印机的心电图形快速打印方法
天花板级固态硬盘,7089MB/S ,aigo国民好物P7000实测
简易机器人的制作
新iPhone方形3摄+A13 但是5G苹果手机尚无时间表