今天这一节我们主要讲解数码管动态显示的原理的程序实现的方法。
图1 数码管同时显示123456
在讲解动态显示方法之前,我们先介绍在种数码管及单片机程序开发过程常用的方法-数组编码法。
1、数组编码
在跟数码管相关的程序中,可以对位进行编码,也可对段进行编码,这里我们以段编码进行讲解。通过第8课的程序我们知道,在位选确定后,要显示数字8时,P0=0x80,显示数字3时P0=0xb0,也就是0xb0,0x80分别可以表示数字3和8,按此方法,我们把在数码管上显示0-f,16个数字全部用16制度表示出来,这16个16进制数就称为数码管可显示0-f的相应的编码,如图2所示(注意共阳和共阴极数码管相应的编码有所不同,这里以实验板上共阳极的为例)。
图2 共阳极数码管编码
在编程中,编码的表示方法如下:
unsigned char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e };
这里编码表示的方法与C语言中数组定义的方法基本一样。table是数组名,后面需加[],中括号中需加上数组中元素的个数,也可以不写。等号的右边用一个大括号将所有元素包含起来,里面的元素之间用“,”隔开,在大括号外用“;”结束。等号左边的unsigned char 是数据元素的数据类型,这里定义为无符号字符型,也就是元素的值范围只能是0-255之间。Code表示把这个数组定义为编码,这样定义的好处是其元素转化成二进文件后可能直接存储到程序存储器中,当然这里也可以不加code,但是这样编译后会将其直接存储到数据存储器中,要知道单片机中数据存储器的容量是非常有限的,定义为code后可节约单片机数据存储器的空间。
调用程序的方法如下,
P0=table[1];
这里表示将数组中的第2个元素(注意第一个是table[0])0xf9赋给P1口,
即P0=0xf9;也就是此时位被选通的数码管会显示数字2.
下面利用编码的方法让6个数码管以间隔1秒的时间循环显示0-f。相应程序如例1.
例1:6个数码管循环显示0-f
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit duan=P2^6;
sbit wei=P2^7;
uchar num;
unsigned char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e };
void delay(uint);
void main()
{
wei=1;
P0=0xfe;
wei=0;
for(num=0;num<16;num++)
{
duan=1;
P0=table[num];
delay(150);
duan=0;
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=500;y>0;y--);
}
下载到实验板后实验现象如图3所示。
图3 6个数码管依次从0-f变化
2、数码管的动态显示
明白了数组编码后,现在我们正式介绍数码管的动态显示,为了更利于大家理解,我们先用前面介绍过的静态显示法写一个程序,功能为:让6个数码管间隔一秒依次显示1、2、3、4、5、6。程序如例2.
例2 数码管依次显示1、2、3、4、5、6
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit duan=P2^6;
sbit wei=P2^7;
uchar num;
uchar code table[]=
{0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint);
void main()
{
while(1)
{
for(num=1;num<7;num++)
{
if(num==1)
{
wei=1;
P0=0xfe;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
else if(num==2)
{
wei=1;
P0=0xfd;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
else if(num==3)
{
wei=1;
P0=0xfb;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
else if(num==4)
{
wei=1;
P0=0xf7;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
else if(num==5)
{
wei=1;
P0=0xef;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
else if(num==6)
{
wei=1;
P0=0xdf;
wei=0;
duan=1;
P0=table[num];
delay(1000);
duan=0;
}
}
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
main函数内的意思num从1开始,一直加到6,然后不断的循环 (程序为for(num=1;num<7;num++),当num=1时,先打开第一位数码管,再让第一位数码管显示1(程序P0=table[num],即P0=table[1]),然后进行1s的延时(程序为delay(1000);)。紧接着当num=2时,打开第二位数码管,并让其显示2,延时1s……,一直到num=6时,打开第六位数码管,并让其显示6,延时1s,再重复前的的程序。这个我们就可以在实验板上看到数码管从第一位开始依次以1s的时间间隔依次显示123456.
下面的程序下载到实验板现象如图4所示。
图4数码管依次显示123456
现在我们把延时程序缩短(注意上面是延时1s,依次100ms 10ms 1ms ….一直到10us,然后把每次改后的程序下载到实验板,.当短到10us时,可看到如下现象:
也就是此时我们看到的现象是6个数码管在同一时刻按位依次显示123456,可能大家马上要提出疑问了,在上面不是说过利用静态的写法不是实现不了这种效果吗?这里就是数码管的动态显示。
所谓动态显示,就是依次向每位位数码管同时送出字形码和相应的位选,位与位之间利用延时程序进行延时,当延时程序非常短时,由于发光管的余辉和人眼视觉暂留作用,此时我们的人眼就分辨不出位与位之间有延时存在,此时就感觉各位数码管同时都在显示,这样我们实现在静态不能实现的功能。