|
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar hour=23,min=59,sec=45; //定義小時(shí)、分鐘和秒變量
uchar count_10ms; //定義10ms計(jì)數(shù)器
sbit K1 = P3^2; //定義K1鍵
sbit K2 = P3^3; //定義K2鍵
sbit K3 = P3^4; //定義K3鍵
sbit K4 = P3^5; //定義K4鍵
sbit BEEP=P3^7; //定義蜂鳴器
bit K1_FLAG=0; //定義按鍵標(biāo)志位,當(dāng)按下K1鍵時(shí),該位置1,K1鍵未按下時(shí),該位為0。
uchar code bit_tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位選表,用來選擇哪一只數(shù)碼管進(jìn)行顯示
uchar code seg_data[]={0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//0,1,2,3,4,5,6,7,8,9,關(guān)顯示,數(shù)碼管碼表
//0~F、熄滅符和字符"-"的顯示碼(字形碼)
uchar disp_buf[8]; //定義顯示緩沖單元
/********以下是延時(shí)函數(shù)********/
void Delay_ms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延時(shí)約xms毫秒
for(j=110;j>0;j--);
}
/*********以下是蜂鳴器響一聲函數(shù)********/
void beep()
{
BEEP=0; //蜂鳴器響
Delay_ms(100);
BEEP=1; //關(guān)閉蜂鳴器
Delay_ms(100);
}
/********以下是走時(shí)轉(zhuǎn)換函數(shù),負(fù)責(zé)將走時(shí)數(shù)據(jù)轉(zhuǎn)換為適合數(shù)碼管顯示的數(shù)據(jù)********/
void conv(uchar in1,in2,in3) //形參in1、in2、in3接收實(shí)參hour、min、sec傳來的數(shù)據(jù)
{
disp_buf[0] =in1/10; // 小時(shí)十位
disp_buf[1] = in1%10; // 小時(shí)個(gè)位
disp_buf[3] = in2/10; // 分鐘十位
disp_buf[4] = in2%10; // 分鐘個(gè)位
disp_buf[6] = in3/10; // 秒十位
disp_buf[7] = in3%10; // 秒個(gè)位
disp_buf[2] = 17; // 第3只數(shù)碼管顯示"-"(在 seg_data表的第17位)
disp_buf[5] = 17; // 第6只數(shù)碼管顯示"-"
}
/********以下是顯示函數(shù)********/
void Display()
{
uchar tmp; //定義顯示暫存
static uchar disp_sel=0; //顯示位選計(jì)數(shù)器,顯示程序通過它得知現(xiàn)正顯示哪個(gè)數(shù)碼管,初始值為0
tmp=bit_tab[disp_sel]; //根據(jù)當(dāng)前的位選計(jì)數(shù)值決定顯示哪只數(shù)碼管
P2=tmp; //送P2控制被選取的數(shù)碼管點(diǎn)亮
tmp=disp_buf[disp_sel]; //根據(jù)當(dāng)前的位選計(jì)數(shù)值查的數(shù)字的顯示碼
tmp=seg_data[tmp]; //取顯示碼
P0=tmp; //送到P0口顯示出相應(yīng)的數(shù)字
disp_sel++; //位選計(jì)數(shù)值加1,指向下一個(gè)數(shù)碼管
if(disp_sel==8)
disp_sel=0; //如果8個(gè)數(shù)碼管顯示了一遍,則讓其回0,重新再掃描
}
/********以下是定時(shí)器T0中斷函數(shù), 用于數(shù)碼管的動(dòng)態(tài)掃描********/
void timer0() interrupt 1
{
TH0 = 0xf8;TL0 = 0xcc; //重裝計(jì)數(shù)初值,定時(shí)時(shí)間為2ms
Display(); //調(diào)顯示函數(shù)
}
/********以下是定時(shí)器T1中斷函數(shù), 用于產(chǎn)生用于產(chǎn)生秒、分鐘和小時(shí)信號(hào)********/
void timer1() interrupt 3
{
TH1 = 0xdc;TL0 = 0x00; //重裝計(jì)數(shù)初值,定時(shí)時(shí)間為10ms
count_10ms++; //10ms計(jì)數(shù)器加1
if(count_10ms >= 100)
{
count_10ms = 0; //計(jì)數(shù)100次后恰好為1s,此時(shí)10ms計(jì)數(shù)器清0
sec++; //秒加1
if(sec == 60)
{
sec = 0;
min++; //若到60秒,分鐘加1
if(min ==60)
{
min = 0;
hour++; //若到60分鐘,小時(shí)加1
if(hour ==24)
{
hour = 0;min=0;sec=0; //若到24小時(shí),小時(shí)、分鐘和秒單元清0
}
}
}
}
}
/********以下是按鍵處理函數(shù),用來對(duì)按鍵進(jìn)行處理********/
void KeyProcess()
{
TR1=0; //若按下K1鍵,則定時(shí)器T1關(guān)閉,時(shí)鐘暫停
if(K2==0) //若按下K2鍵
{
Delay_ms(10); //延時(shí)去抖
if(K2==0)
{
while(!K2); //等待K2鍵釋放
beep();
hour++; //小時(shí)調(diào)整
if(hour==24)
{
hour = 0;
}
}
}
if(K3==0) //若按下K3鍵
{
Delay_ms(10);
if(K3==0)
{
while(!K3); //等待K3鍵釋放
beep();
min++; //分鐘調(diào)整
if(min==60)
{
min = 0;
}
}
}
if(K4==0) //若按下K4鍵
{
Delay_ms(10);
if(K4==0)
{
while(!K4); //等待K4鍵釋放
beep();
TR1=1; //調(diào)整完畢后,時(shí)鐘恢復(fù)走時(shí)
K1_FLAG=0; //將K1鍵按下標(biāo)志位清0
}
}
}
/*********以下是定時(shí)器T0/T1初始化函數(shù)********/
void timer_init()
{
TMOD = 0x11; // 定時(shí)器0, 1工作模式1, 16位定時(shí)方式
TH0 = 0xf8;TL0 = 0xcc; //裝定時(shí)器T0計(jì)數(shù)初值,定時(shí)時(shí)間為2ms
TH1 = 0xdc;TL1 = 0x00; // 裝定時(shí)器T1計(jì)數(shù)初值,定時(shí)時(shí)間為10ms
EA=1;ET0=1;ET1=1; //開總中斷和定時(shí)器T0、T1中斷
TR0 = 1;TR1 = 1; //啟動(dòng)定時(shí)器T0、T1
}
/********以下是主函數(shù)********/
void main(void)
{
P0 = 0xff;
P2 = 0xff;
timer_init(); //調(diào)定時(shí)器T0、T1初始化函數(shù)
while(1)
{
if(K1==0) //若K1鍵按下
{
Delay_ms(10); //延時(shí)10ms去抖
if(K1==0)
{
while(!K1); //等待K1鍵釋放
beep(); //蜂鳴器響一聲
K1_FLAG=1; //K1鍵標(biāo)志位置1,以便進(jìn)行時(shí)鐘調(diào)整
}
}
if(K1_FLAG==1)KeyProcess(); //若K1_FLAG為1,則進(jìn)行走時(shí)調(diào)整
conv(hour,min,sec); //調(diào)走時(shí)轉(zhuǎn)換函數(shù)
}
}
|
|