在第6課里,我們講到數碼管的靜態顯示,利用靜態顯示法,通過控制位選和段選,可以讓數任意幾位數碼管顯示任意字符,但由于所有位數碼管的相同的段選全部接在一起,所以只能同時顯示相同的數字,例如8位同時顯示8字,1、3、5位同時顯示3字。但大家想一下,如果我們要讓數碼管同一時刻顯示不同的數字,如圖1所示的現象,用靜態顯示的方法就不能夠實現,這里就只能用到動態顯示的方法,今天這一節我們主要講解數碼管動態顯示的原理的程序實現的方法。
圖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,可能大家馬上要提出疑問了,在上面不是說過利用靜態的寫法不是實現不了這種效果嗎?這里就是數碼管的動態顯示。
所謂動態顯示,就是依次向每位位數碼管同時送出字形碼和相應的位選,位與位之間利用延時程序進行延時,當延時程序非常短時,由于發光管的余輝和人眼視覺暫留作用,此時我們的人眼就分辨不出位與位之間有延時存在,此時就感覺各位數碼管同時都在顯示,這樣我們實現在靜態不能實現的功能。