#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define duan P1 //段選
#define wei P3 //位選
sbit key1 = P2^3; //設置
sbit key2 = P2^4; //加
sbit key3 = P2^5; //減
sbit key4 = P2^6; //啟動
sbit key5 = P2^7; //手動
sbit out = P2^2; //輸出控制 ,低電平有效
sbit di = P2^0; //蜂鳴器
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
bit flag=0,flag1=0,shan=0;
uchar knum,shan_cont,i;
uchar shi=0,fen=0,miao=0; //時分秒
uint cont,cont1,cont2;
uchar code duanma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共陰段碼表
// 0 1 2 3 5 6 7 8 9
uchar code weima[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位碼 加反相器用
// 1 2 3 4 5 6 7 8
uchar LedBuff[]={0,0,0,0,0,0,0,0}; //數碼管顯示緩沖區
void init() //定時器初始化
{
TMOD |= 0x01; //設置定時器0為工作方式1(M1M0為01)
TH0 = (65536-1000)/256; //1ms初值 @12MHz
TL0 = (65536-1000)%256;
EA = 1; //開總中斷
ET0 = 1; //開定時器0中斷
TR0 = 1; //啟動定時器0
}
void dis() //顯示函數
{
LedBuff[0] = duanma[miao%10];
LedBuff[1] = duanma[miao/10];
LedBuff[2] = 0x40;
LedBuff[3] = duanma[fen%10];
LedBuff[4] = duanma[fen/10];
LedBuff[5] = 0x40;
LedBuff[6] = duanma[shi%10];
LedBuff[7] = duanma[shi/10];
}
void keysan() //按鍵掃描函數
{
static bit kf1=0,kf2=0,kf3=0; //自鎖標志,這里一定要加static(或者用全局變量),否則按鍵不靈
static uint i=0,j=0,k=0,l=0,m=0; //消抖延時變量
//////////////////////////////////////啟動/暫停鍵//////////////////////////////////////
if(knum==0) //只要時分秒都不等于0
{
if(key4 == 1) //啟動 暫停鍵
{
m=0; //按鍵消抖計時變量清零
kf2=0; //按鍵自鎖標志清零
}
else if(kf2 == 0 ) //有按鍵按下,且是第一次被按下
{
++m; //消抖
if( (m>20) && ((miao != 0) || (fen != 0) || (shi != 0)) )
{
//時分秒都為0時,不能啟動輸出,只要其中之一不為0,就能啟動輸出
m=0; //按鍵消抖計時變量清零
kf2=1; //自鎖按鍵置位,避免一直觸發
flag = !flag; //啟動、暫停計時標志
out = !out; //LED狀態取反
}
}
}
//////////////////////////////////////啟動/暫停鍵//////////////////////////////////////
if(out==1) //加這句,只有在輸出關閉的時候,才能設置計時時間,在倒計時的過程中是不能設置的
{
if(key1==1) //設置 //IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
{
i=0; //按鍵消抖計時變量清零
kf1=0; //按鍵自鎖標志清零
}
else if(kf1 == 0) //有按鍵按下,且是第一次被按下
{
++i; //消抖
if(i>12)
{
i=0; //按鍵消抖計時變量清零
kf1=1; //自鎖按鍵置位,避免一直觸發
knum++; //調節時分秒--->123
if(knum==4) knum = 0; //按第四次關閉設置
}
}
}
//////////////////////////////////////加1按鍵//////////////////////////////////////
if(key2==0) //加1按鍵 快速加數
{
j++;
if(j >= 3000) //長按,數碼管掃描放中斷里面,這里的值就要取得大才行
{ //因為沒用delay延時,CPU跑的很快
if(knum==1)
{
miao++; //秒鐘加1
if(miao==60) miao = 0; //超過60s變成0
}
if(knum==2)
{
fen++; //分鐘加1
if(fen==60) fen=0; //超過60變0
}
if(knum==3)
{
shi++; //小時加1
if(shi==24) shi=0; //超過24變0
}
j=1000; //這里j的值可以設置連加的快慢,j的值越大就越快
} //因為初值越大,加到3000的時間就越短
}
else //慢速加數
{
if(j>500 && j<3000)
if(knum==1)
{
miao++; //秒鐘加1
if(miao==60) miao = 0; //超過60s變成0
}
if(knum==2)
{
fen++; //分鐘加1
if(fen==60) fen=0; //超過60變0
}
if(knum==3)
{
shi++; //小時加1
if(shi==24) shi=0; //超過24變0
}
j=0;
}
//////////////////////////////////////減1按鍵//////////////////////////////////////
if(key3==0) //減1按鍵 快速減數
{
k++;
if(k >= 3000) //長按,數碼管掃描放中斷里面,這里的值就要取得大才行
{ //因為沒用delay延時,CPU跑的很快
if(knum==1)
{
miao--; //秒鐘減1
if(miao==255) miao = 59; //小于0就等于59
}
if(knum==2)
{
fen--; //分鐘減1
if(fen==255) fen=59; //小于0就等于59
}
if(knum==3)
{
shi--; //時鐘減1
if(shi==255) shi=23; //小于0就等于23
}
k=1000;
}
}
else
{
if(j>500 && j<3000)
{
if(knum==1)
{
miao--; //秒鐘減1
if(miao==255) miao = 59; //小于0就等于59
}
if(knum==2)
{
fen--; //分鐘減1
if(fen==255) fen=59; //小于0就等于59
}
if(knum==3)
{
shi--; //時鐘減1
if(shi==255) shi=23; //小于0就等于23
}
}
k=0; //消抖變量清零,為下次按鍵做準備
}
////////////////////////////////////////////////////////////////////////////
}
void main()
{
init(); //定時器初始化
out = 1;
while(1)
{
keysan(); //按鍵掃描函數
dis(); //顯示函數
if(shi==0 && fen==0 && miao==0 && flag == 1 ) //倒計時時間到
{
flag=0; //停止計時
flag1=1; //啟動蜂鳴器標志置1
out=1; //關閉輸出
}
}
}
void timer() interrupt 1
{
TH0 = (65536-1000)/256; //1毫秒初值
TL0 = (65536-1000)%256;
//////////////////////////////////////1s計時//////////////////////////////////////
if(flag)
{
cont++;
if(cont == 1000) //1s到
{
cont = 0; //清0
miao--; //秒數減1
if(miao==255) //如果小于0,就是59
{
miao=59;
fen--; //分鐘數減1
if(fen==255) //如果小于0,就是59
{
fen=59;
shi--; //小時減1
if(shi==255) shi=0; //時鐘小于0,就是0
if(shi==0) fen=59; //時鐘小于0,就是255
if(fen==0 && shi==0) fen=0;//時鐘分鐘都為0,就是0
}
}
}
}
//////////////////////////////////////蜂鳴器控制//////////////////////////////////////
if(flag1) //倒計時時間到,啟動蜂鳴器
{
cont1++;
if(cont1==500) //500ms蜂鳴器響一次
{
cont1=0;
di=!di;
cont2++;
if(cont2==20)//500*20=10000ms=10s,蜂鳴器響10s后停止
{
cont2=0;
flag1=0;
}
}
}
//////////////////////////////////////啟動/暫停鍵//////////////////////////////////////
if(knum != 0)
{
shan_cont++;
if(shan_cont==100) //設置時,100ms閃爍時間 可根據實際效果調整
{
shan_cont=0;
shan = !shan;
}
}
/**********************************數碼管掃描函數**********************************/
i++; //挨個顯示
if(i>=8) i=0; //清0
duan = 0x00;
switch(i)
{
case 0:
if(knum==1) //如果設置鍵第一次按下
{
if(shan==1) {wei = 0x00; duan = LedBuff[0];} //設置秒位閃爍
else {wei = weima[0]; duan = LedBuff[0];}
}
else{wei = weima[0]; duan = LedBuff[0];} break; //否則正常顯示
case 1:
if(knum==1) //如果設置鍵第一次按下
{
if(shan==1){wei = 0x00; duan = LedBuff[1];} //設置秒位閃爍
else{wei = weima[1]; duan = LedBuff[1];}
}
else{wei = weima[1]; duan = LedBuff[1];} break; //否則正常顯示
case 2: wei = weima[2]; duan = LedBuff[2]; break; //顯示-
case 3:
if(knum==2) //如果設置鍵第二次按下
{
if(shan==1){wei = 0x00; duan = LedBuff[3];} //設置分位閃爍
else{wei = weima[3]; duan = LedBuff[3];}
}
else{wei = weima[3]; duan = LedBuff[3];} break;//否則正常顯示
case 4:
if(knum==2) //如果設置鍵第二次按下
{
if(shan==1){wei = 0x00; duan = LedBuff[4];} //設置分位閃爍
else{wei = weima[4]; duan = LedBuff[4];}
}
else{wei = weima[4]; duan = LedBuff[4];} break; //否則正常顯示
case 5: wei = weima[5]; duan = LedBuff[5]; break; //顯示-
case 6:
if(knum==3) //如果設置鍵第三次按下
{
if(shan==1){wei = 0x00; duan = LedBuff[6];} //設置時位閃爍
else{wei = weima[6]; duan = LedBuff[6];}
}
else{wei = weima[6]; duan = LedBuff[6];} break;//否則正常顯示
case 7:
if(knum==3) //如果設置鍵第三次按下
{
if(shan==1){wei = 0x00; duan = LedBuff[7];} //設置時位閃爍
else{wei = weima[7]; duan = LedBuff[7];}
}
else{wei = weima[7]; duan = LedBuff[7];} break;//否則正常顯示
default: break;
}
}
感謝大佬回信,我聽你的建議加了在if(key2==0)的else里加了短按判斷if(j>500 && j<3000),秒表問題解決,但我時分顯示也有這個問題,我改了幾次發現不行不知道怎么改了 |