說明: 驅動四位一體數碼管動態顯示數字,可方便的移植到其它程序中。
例如:1、硬件改為三位一體或二位一體數碼管,只需修改Display_Scan()函數COM個數。
2、本例中,采用了共陰數碼管,如果用在共陽數碼管,只需修改相應段碼表。
本程序使用P0口作為段碼數據發送端,P2.0-P2.3作為數碼管掃描選通,
使用P0口時,因單片機內部沒有上拉電阻,所以要外接上拉電阻(參考阻值470歐姆).
// STC89C52RC
// +---------------+
// | |
// | | Digital Number
// | | _______________________
// | | | __ __ __ __ |
// | P0.0--P0.7|===>| | | | | | | | | |
// | (a,b...g,h)| | |--| |--| |--| |--| | 4位共陰數碼管
// | | | |__|.|__|.|__|.|__|.|
// | | -----------------------
// | | | | | |
// | | | | | |
// | P2.7(COM3)|--------+ | | |
// | | | | |
// | P2.6(COM2)|-------------+ | |
// | | | |
// | P2.5(COM1)|------------------+ |
// | | |
// | P2.4(COM0)|-----------------------+
// +---------------+
#include
// 函數聲明
//=======================================================================
void DisplayNumber(unsigned int Num);
void delayms( int ms);
//=======================================================================
unsigned char code LED_table[]={ //使用附帶“51單片機工具箱”可以很容易編碼
0x3f, //"0"
0x06, //"1"
0x5b, //"2" AAAA
0x4f, //"3" F B
0x66, //"4" F B
0x6d, //"5" GGGG
0x7d, //"6" E C
0x07, //"7" E C
0x7f, //"8" DDDD H
0x6f, //"9"
0x00, //black
0x80 //dot
};
#define black 10 // 空白
#define dot 11 // 小數點
unsigned char DisBuff[4]; //定義顯示緩沖數組
unsigned char COM;
// 定義通信端口
//===========================================================================
sbit COM0=P2^4;
sbit COM1=P2^5; //對應口線由硬件確定
sbit COM2=P2^6;
sbit COM3=P2^7;
//===========================================================================
void Sys_Init()
{
TMOD=0x01; //定時器/計數器0為定時器方式 16位工作模式
TH0=(65536-1000)/256; //初始時間常數
TL0=(65536-1000)%6; //1.0ms
ET0=1; //定時器/計數器0中斷允許
EA=1; //總中斷允許
TR0=1; //啟動定時器/計數器開始工作
}
void DisplayNumber(unsigned int Num) //顯示程序
{
unsigned char i;
EA=0; //禁止總中斷
for(i=0;i<4;i++)
{
DisBuff[i]=Num; //拆分數字
Num/=10;
}
for(i=3;i>=0;i--) //循環4次
{
if (DisBuff[i]==0) DisBuff[i]=black; //消隱無效"0"
else break; //例如將 0123 改成 123,僅顯示有效數字
}
EA=1; //總中斷允許
}
void Display_Scan() interrupt 1 // 中斷服務程序,數碼管選通掃描
{
TR0=0;
TH0=(65536-1000)/256; //高8位和低8位時間常數
TL0=(65536-1000)%6;
TR0=1; //啟動定時器0
if(COM>3) COM=0;
COM0=COM1=COM2=COM3=1; //將COM0-COM3置1,全暗
switch(COM)
{
case 0: P0=LED_table[DisBuff[0]]; COM0=0; break; //分別選通COM0-COM3 低電平有效
case 1: P0=LED_table[DisBuff[1]]; COM1=0; break;
case 2: P0=LED_table[DisBuff[2]]; COM2=0; break;
case 3: P0=LED_table[DisBuff[3]]; COM3=0; break;
} // 與decp(0x20)位或,恰好點亮小數點位段
COM++;
}
void delayms(int ms)
{
unsigned int i;
for(;ms>0;ms--) //循環ms次
{
for(i=0;i<123;i++); // for(i=0;i<123;i++); 每次1ms延遲@ 12.0MHz
} // for(i=0;i<113;i++); 每次1ms延遲@ 11.0592MHz
}
void main()
{
unsigned int i; //定義變量
Sys_Init(); //初始化timer0
while(1) //死循環,單片機必須是死循環
{
DisplayNumber(i); //調用數碼管顯示函數
delayms(200); //調用延時函數,使顯示數字保持一段時間
i++; //這里演示一個數字累加的程序
//也可以直接寫一個常數用來顯示,看實際效果
} //例如DisplayNumber(1234); 編譯后將HEX文件
} //下載到學板里應該正常顯示數字 1234 。
// 另一種段編碼方法
//===========================================================================
//宏定義,數碼管a-g各段對應的比特,更換硬件只用改動以下8行
#define a 0x04 // AAAA
#define b 0x01 // F B
#define c 0x10 // F B
#define d 0x40 // GGGG
#define e 0x80 // E C
#define f 0x02 // E C
#define g 0x08 // DDDD H
#define h 0x20
//用宏定義自動生成段碼表,很好的寫法,值得學習
//更換硬件無需重寫段碼表
unsigned char code LED_table[]={
a+b+c+d+e+f, //"0"
b+c, //"1"
a+b+d+e+g, //"2"
a+b+c+d+g, //"3"
b+c+f+g, //"4"
a+c+d+f+g, //"5"
a+c+d+e+f+g, //"6"
a+b+c, //"7"
a+b+c+d+e+f+g, //"8"
a+b+c+d+f+g, //"9"
b+c+e+f+g, //"H"
a+f+e+g, //"C"
d+e+f, //"L"
g, //"-"
0x00 //black
};
#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
#undef g