|
|
#include<reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code LedChar[]={ //數(shù)碼管顯示字符轉(zhuǎn)換表
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};
unsigned char Ledbuff[6] = { //數(shù)碼管顯示緩沖區(qū)
0x00,0x00,0x00,0x00,0x00,0x00
};
unsigned char KeySta[4]={ //按鍵當(dāng)前狀態(tài)
1,1,1,1
};
u8 T0RH = 0;
u8 T0RL = 0;
bit StopwatchRefresh=1; //秒表計數(shù)刷新標(biāo)志
bit StopwatchRunning=0; //秒表運(yùn)行標(biāo)志
u8 DecimalPart = 0; //小數(shù)部分定義
u16 IntegerPart = 0; //整數(shù)部分定義
void ConfigTimer0(u16 ms);
void KeyDriver();
void StopwatchDisplay();
void main(void)
{
EA=1;
ConfigTimer0(2); //定時器周期函數(shù)
while(1)
{
if(StopwatchRefresh)
{
StopwatchRefresh=0; //秒表狀態(tài)位
StopwatchDisplay(); //秒表顯示函數(shù)
}
KeyDriver(); //按鍵驅(qū)動函數(shù)
}
}
void ConfigTimer0(u16 ms)
{
unsigned long tmp;
tmp=12000000/12;
tmp=(tmp*ms)/1000;
tmp=65536-tmp;
T0RH=(u8)(tmp>>8);
T0RL=(u8)tmp;
TMOD&=0XF0;
TMOD|=0X01;
TH0=T0RH;
TL0=T0RL;
ET0=1;
TR0=1;
}
void StopwatchDisplay()
{
signed char i;
u8 buf[4]; //數(shù)據(jù)轉(zhuǎn)換的緩沖區(qū)
//小數(shù)部分轉(zhuǎn)換到低2位
Ledbuff[0] = LedChar[DecimalPart%10];
Ledbuff[1] = LedChar[DecimalPart/10];
//整數(shù)部分轉(zhuǎn)換到高4位
buf[0] = IntegerPart%10;
buf[1] = (IntegerPart/10)%10;
buf[2] = (IntegerPart/100)%10;
buf[3] = (IntegerPart/1000)%10;
for(i=3;i>1;i--) //整數(shù)部分高位的0 轉(zhuǎn)換為空字符
{
if(buf == 0)
{
Ledbuff[i+2] = 0xfe;
}
else
break;
}
for(;i>0;i--) //有效數(shù)字位轉(zhuǎn)換為顯示字符
{
Ledbuff[i+2] = LedChar[buf];
}
Ledbuff[2] &= 0x7f; //點(diǎn)亮小數(shù)點(diǎn)
}
/*秒表啟停函數(shù)*/
void StopwatchAction()
{
if(StopwatchRunning) //已啟動則停止
StopwatchRunning = 0;
else //未啟動則啟動
StopwatchRunning = 1;
}
/* 秒表復(fù)位函數(shù) */
void StopwatchReset()
{
StopwatchRunning = 0; //停止秒表
DecimalPart = 0; //清零計數(shù)值
IntegerPart = 0;
StopwatchRefresh =1; //置刷新標(biāo)志
}
/* 按鍵驅(qū)動函數(shù),檢測按鍵動作,調(diào)度相應(yīng)動作函數(shù),需在主循環(huán)中調(diào)用 */
void KeyDriver()
{
u8 i;
static u8 backup[4] = {1,1,1,1}; //按鍵上一次的狀態(tài)
for(i=0;i<4;i++) //循環(huán)檢測4個按鍵
{
if(backup!= KeySta) //按鍵狀態(tài)改變
{
if(backup != 0) //按鍵按下
{
if(i == 1) //Key1鍵復(fù)位秒表
StopwatchReset();
if( i== 2) //Key2鍵啟停秒表
StopwatchAction();
}
backup = KeySta; //刷新前一次的備份值
}
}
}
/* 秒表計數(shù)函數(shù),每隔10ms 調(diào)用一次進(jìn)行秒表計數(shù)累加 */
void StopwatchCount()
{
if(StopwatchRunning) //當(dāng)處于運(yùn)行狀態(tài)時遞增計數(shù)值
{
DecimalPart++; //小數(shù)部分+1
if(DecimalPart >= 100) //小數(shù)部分計到100 時進(jìn)位到整數(shù)部分
{
DecimalPart = 0;
IntegerPart++; //整數(shù)部分+1
if(IntegerPart >= 10000)
{
IntegerPart = 0;
}
}
StopwatchRefresh = 1;
}
}
/* 數(shù)碼管動態(tài)掃描刷新函數(shù),需在定時中斷中調(diào)用 */
void LedScan()
{
static u8 i;
P0=0X00;
switch(i)
{
case 0:LSA=0;LSB=0;LSC=0;i++;P0=Ledbuff[0];break;
case 1:LSA=1;LSB=0;LSC=0;i++;P0=Ledbuff[1];break;
case 2:LSA=0;LSB=1;LSC=0;i++;P0=Ledbuff[2];break;
case 3:LSA=1;LSB=1;LSC=0;i++;P0=Ledbuff[3];break;
case 4:LSA=0;LSB=0;LSC=1;i++;P0=Ledbuff[4];break;
case 5:LSA=1;LSB=0;LSC=1;i++;P0=Ledbuff[5];break;
default:break;
}
}
/* 按鍵掃描函數(shù),需在定時中斷中調(diào)用 */
void KeyScan()
{
u8 i;
static u8 keybuf[4] = { //按鍵掃描初始化
0xFF,0xFF,0xFF,0xFF
};
//按鍵值移入緩沖區(qū)
keybuf[0] = (keybuf[0] << 1) | KEY1;
keybuf[1] = (keybuf[1] << 1) | KEY2;
keybuf[2] = (keybuf[2] << 1) | KEY3;
keybuf[3] = (keybuf[3] << 1) | KEY4;
//消抖后更新按鍵狀態(tài)
for(i=0;i<4;i++)
{
if(keybuf == 0x00) //連續(xù)8次掃描為0,即16ms內(nèi)都是彈起狀態(tài),可認(rèn)為按鍵已按下
KeySta=0;
else if(keybuf == 0xFF) //連續(xù)8次掃描為1,即16ms內(nèi)都是按下狀態(tài),可認(rèn)為按鍵已按下
KeySta=1;
}
}
/*中斷服務(wù)函數(shù),完成數(shù)碼管,按鍵掃描與秒表計數(shù)*/
void Timer0() interrupt 1
{
static unsigned char tmr10ms;
TH0 = T0RH;
TL0 = T0RL;
LedScan(); //數(shù)碼管顯示
KeyScan(); //按鍵掃描
tmr10ms++;
if(tmr10ms >= 5)
{
tmr10ms = 0;
StopwatchCount(); //調(diào)用秒表計數(shù)函數(shù)
}
}
|
|