此程序是在51hei單片機開發(fā)板上面做的,如需要移植到自己的電路上,修改相應(yīng)的端口即可,開發(fā)板完整的電路圖下載: 點這里 (注意:只需要看相關(guān)部分即可,其他部分可以忽略)
/**
****************************************************************************************
*file : main.c
*author : xr
*date : 2014年4月15日10:08:26 - 2014年4月15日12:40:51
*version: V1.2.3
*brief : Stopwatch數(shù)碼管顯示-實用秒表 單片機STC89C52RC MCU 晶振 11.0592MHZ
****************************************************************************************
*/
#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY_IN_1 = P2^4;//列
sbit KEY_IN_2 = P2^5;
sbit KEY_IN_3 = P2^6;
sbit KEY_IN_4 = P2^7;
unsigned char code LedTable[] = {
0xC0, //"0"
0xF9, //"1"
0xA4, //"2"
0xB0, //"3"
0x99, //"4"
0x92, //"5"
0x82, //"6"
0xF8, //"7"
0x80, //"8"
0x90, //"9"
0x88, //"A"
0x83, //"B"
0xC6, //"C"
0xA1, //"D"
0x86, //"E"
0x8E //"F"
};
unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
bit stopwatchRunning = 0;//秒表啟動和停止標(biāo)志
unsigned char thr0, tlr0;//T0重載值的高低字節(jié)
unsigned char decimal = 0;//小數(shù)位
unsigned int integer = 0;//整數(shù)位
/****************function definition**********************/
void Initial();
void ConfigTimer0(unsigned long xms);
void StopwatchDisplay();
void KeyAction();
void main(void)
{
Initial();
ConfigTimer0(1);//定時1ms
{
KeyAction(); //檢測按鍵動作
if (flag10ms) //10ms檢測秒表的運行狀態(tài),當(dāng)stopwatchRunning標(biāo)志=1時進行計時++,否則就停止計時
{
flag10ms = 0;
if (stopwatchRunning) //10ms刷新秒表計數(shù)
{
decimal++;
if (decimal >= 100)
{
decimal = 0;
integer++;
if (integer >= 10000)
{
integer = 0;
}
}
StopwatchDisplay();//分解decimal和integer,存入LedBuff數(shù)碼管緩沖區(qū)
}
}
}
}
void Initial()
{
ADDR3 = 1;
ENLED = 0;//選擇數(shù)碼管
P2 = 0xFE; //選擇第四行按鍵檢測(原理圖上是第四列)
LedBuff[0] = LedTable[decimal % 10]; //初始顯示0.00
LedBuff[1] = LedTable[decimal / 10 % 10];
LedBuff[2] = LedTable[integer % 10];
LedBuff[2] &= 0x7F;//點亮小數(shù)點
}
void ConfigTimer0(unsigned long xms)
{
unsigned long tmp;//32bit 注意:此處必須用unsigned long 數(shù)據(jù),因為11059200已經(jīng)超出了16位unsigned int
tmp = 11059200/12;//單片機的機器周期頻率
tmp = (tmp * xms) / 1000;//定時xms所需的頻率
tmp = 65536-tmp;//定時xms的初始裝載值
tmp += 18; //補償值
thr0 = (unsigned char)(tmp >> 8);
tlr0 = (unsigned char)tmp;
TMOD &= 0xF0;//清零T0控制位
TMOD |= 0x01;//配置T0工作在方式1,16位可設(shè)定定時器
TH0 = thr0;
TL0 = tlr0;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void LedCharRefresh()
{
static unsigned char j = 0;
P0 = 0xFF;//消隱
P0 = LedBuff[j++];
if (j > 5)
j = 0;
}
void StopwatchDisplay()
{
signed char i = 0;
unsigned char buf[6];
buf[1] = decimal / 10 % 10;
buf[3] = integer / 10 % 10;
buf[4] = integer / 100 % 10;
buf[5] = integer / 1000 % 10;
{
if (buf[i] == 0)
buf[i] = 0xFF;
else
break;
}
//處理有效位
for (; i >=0; i--)
{
buf[i] = LedTable[buf[i]]; //轉(zhuǎn)為實際的數(shù)字
}
//拷貝
for (i = 0; i <= 5; i++)
{
LedBuff[i] = buf[i];//拷貝到顯示緩沖區(qū)
}
LedBuff[2] &= 0x7F;//點亮小數(shù)點
}
void StopwatchAction()
{
if (stopwatchRunning) //當(dāng)前狀態(tài)為運行
{
stopwatchRunning = 0; //停止運行
}
else
{
stopwatchRunning = 1; //啟動
}
}
void StopwatchReset()
{
stopwatchRunning = 0;//停止秒表計時
decimal = 0;
integer = 0;//清零
StopwatchDisplay();//顯示
}
void KeyAction()
{
static unsigned char keybackup[4] = {1, 1, 1, 1};//按鍵的備份值(前一次按鍵值) 必須是靜態(tài)的
unsigned char i = 0;
{
if (keybackup[i] != KeySta[i]) //按鍵的上一次的狀態(tài)和當(dāng)前狀態(tài)不相同,即按鍵有動作
{
if (keybackup[i] != 0) //如果上一次按鍵的值是1,則此時按鍵是按下動作
{
switch (i)
{
case 1: StopwatchReset(); break; //ESC鍵秒表復(fù)位
case 2: StopwatchAction(); break; //Enter鍵控制秒表的啟動和停止
default: break;
}
}
keybackup[i] = KeySta[i];//備份當(dāng)前按鍵值
}
}
}
void KeyScan()
{
static unsigned char KeyBuf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; //按鍵掃描緩沖區(qū)
unsigned char i = 0;
//檢測一行按鍵的狀態(tài)并存入按鍵檢測緩沖區(qū)中
KeyBuf[0] = (KeyBuf[0] << 1) | KEY_IN_1;
KeyBuf[1] = (KeyBuf[1] << 1) | KEY_IN_2;
KeyBuf[2] = (KeyBuf[2] << 1) | KEY_IN_3;
KeyBuf[3] = (KeyBuf[3] << 1) | KEY_IN_4;
for (i = 0; i < 4; i++)
{
if ((KeyBuf[i] & 0xFF) == 0x00)
KeySta[i] = 0;//8次檢測按鍵狀態(tài)都是0,即按鍵穩(wěn)定按下
else if ((KeyBuf[i] & 0xFF) == 0xFF)
KeySta[i] = 1;//8次檢測按鍵的狀態(tài)都是1,即按鍵穩(wěn)定彈起
}
}
void Timer0_ISP() interrupt 1
{
static unsigned char counter = 0;//計數(shù)器
TL0 = tlr0;//重新裝載定時器初值
counter++;
LedCharRefresh();//數(shù)碼管刷新
KeyScan(); //按鍵掃描
{
counter = 0;
flag10ms = 1;
}
}