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