時鐘及規定時間鬧鐘
題目要求:用按鍵設定時鐘的時、分、秒。要求用4鍵方式,即選擇、加、減、确認鍵,選擇鍵用于選擇修改起始時、分、秒值,每按一次,被修改數位管順序移動并閃爍。用+,- 鍵修改數值,确認鍵确定修改結束。用掃描方式動态顯示時、分、秒,第2,4 數位管加小數點,并且要求第4數位管小數點每秒閃爍一次。可以設定鬧鐘,到時間蜂鳴器報警
難點及技巧:
1、通過在定時器中斷來設定标志位來控制數位管的閃爍
2、八位數位管小數點的點亮,0x80,通過或與句(|0x80)
3、數位管的閃爍,通過if語句,對标志位進行求餘(閃爍,對2求餘即可)
話不多說,直接看代碼
代碼講解:
源代碼:
#include "reg52.h" //此檔案中定義了單片機的一些特殊功能寄存器
#include<intrins.h>
typedef unsigned int u16; //對資料類型進行聲明定義
typedef unsigned char u8;
sbit LSA=P2^2; //38譯碼器
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit buzz=P2^5; //蜂鳴器
sbit k1=P3^1; //選擇鍵
sbit k2=P3^0; //加一
sbit k3=P3^2; //減一
sbit k4=P3^3; //确認健
//數位表
u8 code lzl[17]={ 0x3f,0x06,0x5b,
0x4f,0x66,0x6d,
0x7d,0x07,0x7f,
0x6f,0x77,0x7c,
0x39,0x5e,0x79,
0x71};
u8 ssec,sec,min,hour; //毫秒,秒,分,時
u8 model,sign; //标志位
u8 wei[8];
u8 uhour=0,umin=0,usec=5; //鬧鐘時間設定
void delay(u16 i); //延時函數
void Timer0Init(); //中斷函數初始化
void display(); //動态顯示
void show(); //顯示數位管
void key_scan(); //按鍵功能 k1:選擇健 k2:加一 k3:減一 k4:确認健
void start(); //函數總和
void delay(u16 i) //延時函數
{
while(i--);
}
void Timer0Init()
{
TMOD|=0X01;//選擇為定時器0模式,工作方式1,僅用TR0打開啟動。
TH0=0Xd8; //給定時器賦初值,定時10ms
TL0=0Xf0;
ET0=1;//打開定時器0中斷允許 //注:稍後用K2控制總中斷,實作暫停功能
EA=1;//打開總中斷
TR0=1;//打開定時器 防止未按就計時
}
//動态顯示函數
void display()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位選,選擇點亮的數位管,
{
case(0):
LSA=1;LSB=1;LSC=1; break;
case(1):
LSA=0;LSB=1;LSC=1; break;
case(2):
LSA=1;LSB=0;LSC=1; break;
case(3):
LSA=0;LSB=0;LSC=1; break;
case(4):
LSA=1;LSB=1;LSC=0; break;
case(5):
LSA=0;LSB=1;LSC=0; break;
case(6):
LSA=1;LSB=0;LSC=0; break;
case(7):
LSA=0;LSB=0;LSC=0; break;
}
P0=wei[i]; //發送段碼
delay(100); //間隔一段時間掃描
P0=0x00;
}
}
//記錄數位管顯示
void show()
{
wei[2]=0;
wei[5]=0;
switch(model)
{
case 0:
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
break;
}
case 1:
{
if(sign%2==0)
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=0x00;
wei[7]=0x00;
}
else
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
}
break;
}
case 2:
{
if(sign%2==0)
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=0x00;
wei[4]=0x00|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
}
else
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
}
}
break;
case 3:
{
if(sign%2==0)
{
wei[0]=0x00;
if(sign%2==0)
wei[1]=0x00|0x80;
else
wei[1]=0x00;
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
}
else
{
wei[0]=lzl[hour/10];
if(sign%2==0)
wei[1]=lzl[hour%10]|0x80;
else
wei[1]=lzl[hour%10];
wei[3]=lzl[min/10];
wei[4]=lzl[min%10]|0x80;
wei[6]=lzl[sec/10];
wei[7]=lzl[sec%10];
}
break;
}
}
}
//按鍵掃描及處理
void key_scan()
{
if(k1==0)
{
delay(1000);
if(k1==0)
{
model++;
while(!k1);
if(model==4)
model=0;
}
}
if(k2==0)
{
delay(1000);
if(k2==0)
{
if(model==1) //修改秒
{
sec++; if(sec>=60)sec=0;
}
else if(model==2) //修改分鐘
{
min++; if(min>=60)min=0;
}
else if(model==3) //修改小時
{
hour++; if(hour>=24)hour=0;
}
while(!k2);
}
}
if(k3==0)
{
delay(1000);
if(k3==0)
{
if(model==1) //修改秒
{
sec--; if(sec==255)sec=59;
}
else if(model==2) //修改分鐘
{
min--; if(min==255)min=59;
}
else if(model==3) //修改小時
{
hour--; if(hour==255)hour=23;
}
while(!k3);
}
}
if(k4==0) //恢複初态
{
delay(1000);
if(k4==0)
model=0;
while(!k4);
}
if(min==umin) //鬧鐘,自己定義時間
{
if(hour==uhour)
{
if(sec==usec)
{
buzz=~buzz;
}
}
}
}
void start()
{
display();
show();
key_scan();
}
//主函數
void main()
{
Timer0Init(); //設定外部中斷
while(1)
{
start();
}
}
void Timer0() interrupt 1
{
TH0=0Xd8; //給定時器賦初值,定時10ms
TL0=0Xf0;
ssec++;
if(ssec>=100) //1s
{
ssec=0;
sec++;
sign++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)
{
hour=0;
}
}
}
}
}