数码管静态显示
以八段管为例介绍其字段,八段数码管其实是由八个LED灯组成的8字型,如图8.2所示,这八个灯按逆时针方向分别为:a,b,c,d,e,f,g,h。如果要显示“7”字,只需要将a,b,c三个灯点亮即可,如图8.3所示:
这样来理解的话,要点亮一个数码管很容易,其实就是点亮相应的LED灯,就能显示不同的数字。我们在前面的实验中已经知道怎么点亮开发板上的LED灯,就是用单片机的I/O脚向LED灯输出低电平,灯就能点亮,输出高电平,灯就熄灭。那我们点亮数码管上的LED灯是不是也是这样呢?这就涉及到数码管是共阳极的还是共阴极的。
3、数码管工作原理详解
我们先以一位数码管为例。数码管的共阳极工作方式和共阴极工作方式对初学者而言可能不太好理解,为了加强理解下面把数码管简化,如图8.4所示:
上图中的DP就是前边图中的h,也就是小数点,图中的数字是数码管的引脚,一位数码管管脚如图8.5所示,大家
可以对照看,找到数码管各个字段对应哪个引脚。这里主要看字母。从图中可以看出数码管其实就是多个发光二极管的集合体。
共阴数码管:将发光二极管的阴极共同连接在一起;
共阳数码管:将发光二极管的阳极共同连接在一起;
对共阳数码管而言,如果要显示“7”字,公共端给高电平,A,B,C给低电平,D,E,F,G,DP给高电平就可以了。如图8.6所示。
回到我们本次课要完成的实验中来,本次实验我们要实现用程序将开发板上最左边的数码管显示任意的数字。我们还是从两方面考虑:硬件设计和软件设计。
1、硬件设计
本实验板上的数码管使用的是共阴极数码管,硬件上将最左边数码管的共阴极引脚也就是实验板上的LED_CH1插针接到GND上,A到DP段的阳极引脚也就是实验板上的LED_DAT1到LED_DAT8插针按顺序接到P20到P27上。
2、软件设计
1)数据结构
因为显示码在程序运行中不会改变,可以在程序存储器中定义一个显示码数组,数组里的值按从0到9的显示码的顺序存放,定义的格式为:
unsigned char code display_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
2)软件代码
下面是让第一个数码管显示5的程序代码。
#include"REG51.h"
#include"intrins.h"
unsigned char code display_code[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
void main(void)
{
unsigned int i;
P0=0xfe;
P2=display_code[5]; //将5的显示码赋给P2口,数码管显示5
while(1);
}
数码管动态显示
上次课我们了解了一位数码管显示数据的原理,但在实际应用中往往需要多位数码管,例如我们要做电子表,我们就需要8位数码管,来显示时、分、秒。当我们需要多位数码管时,我们不需要买多个一位的数码管,可以买多位的数码管,例如两位的或四位的,如图10.2.1所示。本开发板上使用的是两个4位的数码管,我们先来认识一下4位数码管的结构及引脚,图10.2.2为4位数码管引脚图,数码管正面的左下角为第1引脚,按逆时针顺序,左上方第12引脚。
#include"REG51.h"
unsigned char code display_code[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit P00=P0^0;
sbit P01=P0^1;
void main(void)
{
while(1)
{
P00=1;
P01=0;
P2=display_code[1]; //将1的显示码赋给P2口,第一个数码管显示1
P00=0;
P01=1;
P2=display_code[1]; //将2的显示码赋给P2口,第二个数码管显示2
}
}
将上面的代码编译下载到实验板上运行,发现两个数码管显示不清楚并且有重影,大家思考一下这是什么原因呢?这是因为上面的代码让一个数码管显示后,显示还没稳定,就立马就关闭,显示另一个数码管。要解决这个问题,需要每个数码管显示后加一定的延时,等显示稳定后,再显示另一个数码管,将上面的代码加上延时代码如下:
将上面的代码编译下载到实验板上,发现两个数码管是很清楚的显示“1”和“2”,但会跳动,那是因为延时时间太长,人的眼睛存在“视觉驻留效应”,如果,人眼就会感觉到跳动,只有让关闭某位数码管到下次再次点亮的时间间隔小于眼睛的驻留时间,也就是眼睛还没觉察到数码管熄灭,就再次的点亮,就可以给人一种稳定的显示效果。把上面代码中的延时时间缩短,修改代码如下:
#include"REG51.h"
unsigned char code display_code[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
sbit P00=P0^0;
sbit P01=P0^1;
void main(void)
{
unsigned int i;
while(1)
{
P2=0xff;
P00=1;
P01=0;
P2=display_code[1]; //将1的显示码赋给P2口,第一个数码管显示1
for(i=0;i<500;i++); //延时一段时间
P2=0xff;
P00=0;
P01=1;
P2=display_code[2]; //将2的显示码赋给P2口,第二个数码管显示2
for(i=0;i<500;i++); //延时一段时间
}
}
将上面的代码编译下载到实验板上,发现两个数码管是很清楚、稳定的显示“1”和“2”。我们把上面数码管的显示方法称为数码管动态显示。用数码管显示信息时,由于每个数码管至少需要8 个I/O 口,如果需要多个数码管,则需要太多I/O 口,而单片机的I/O 口是有限的。在实际应用中,一般采用动态显示的方式解决此问题。动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出显示码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。在动态显示程序中,各个数码管显示的延时时间长短是非常重要的,如果延时时间长,则会出现闪烁现象;如果延时时间太短,则会出现显示暗且有重影。
八位数码管显示
上次课讲解了数码管动态显示原理,并利用数码管动态显示原理,实现了在两个数码管上同时显示“12”。下面我们讲解上次课布置的作业,在八个数码管上同时显示“12345678”。硬件上,我们顺着两位数码管的显示的硬件连线,将另外六个数码管的选择线LED_CH3到LED_CH8按顺序分别接到P02到P07引脚上。软件上,只要在两位显示的基础上,用同样的方法再增加另外6个数码管的显示,代码如下:
#include"REG51.h"
unsigned char code display_code[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
sbit P04=P0^4;
sbit P05=P0^5;
sbit P06=P0^6;
sbit P07=P0^7;
void main(void)
{
unsigned int i;
while(1)
{
P2=0xff;//如果不加P2=0xff;的话只会显示1234567,而8是显示不出来的
P00=0;//选择第一个数码管
P01=1;
P02=1;
P03=1;
P04=1;
P05=1;
P06=1;
P07=1;
P2=display_code[1]; //将1的显示码赋给P2口,第一个数码管显示1
for(i=0;i<500;i++); //延时一段时间
P2=0xff;
P00=1;
P01=0;//选择第二个数码管
P02=1;
P03=1;
P04=1;
P05=1;
P06=1;
P07=1;
P2=display_code[2]; //将2的显示码赋给P2口,第二个数码管显示2
for(i=0;i<500;i++); //延时一段时间
P2=0xff;
P00=1;
P01=1;
P02=0;//选择第三个数码管
P03=1;
P04=1;
P05=1;
P06=1;
P07=1;
P2=display_code[3]; //将3的显示码赋给P2口,第三个数码管显示3
for(i=0;i<500;i++); //延时一段时间
P00=1;
P01=1;
P02=1;
P03=0;//选择第四个数码管
P04=1;
P05=1;
P06=1;
P07=1;
P2=display_code[4