用STC89c52單片機,12M晶振。計時用T2定時器,16位自動重裝模式 基本功能如下: 可以顯示年份、月、日、時間,有鬧鐘功能,有倒計時功能。 上電默認顯示時間,可通過按鍵切換顯示年份、日期、鬧鐘、倒計時,顯示一定時間后自動返回到時間顯示。 在相應的顯示狀態下按設置鍵進行相應的設置。如在時間顯示時按設置鍵可調整時間。其余類推倒計時最多可以倒數99小時59分59秒,設置完倒計時時間后進入倒數狀態,閃爍顯示倒數時間,中途可按鍵退出,倒數結束后鈴響1分鐘返回時間顯示。 鬧鐘可選擇開或關,鬧鈴響1分鐘停止。
電路原理圖如下:
0.png (86.33 KB, 下載次數: 90)
下載附件
2018-10-16 01:46 上傳
制作出來的實物圖如下:
微信截圖_20181015211114.png (338.23 KB, 下載次數: 84)
下載附件
2018-10-15 21:11 上傳
單片機源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define DispOFF 10; //顯示關
- #define POINT 21; //顯示小點
- #define F 22;
- #define H 23;
- #define M 24;
- #define N 25;
- #define O 26;
- sbit buzzer=P3^7; //蜂鳴器控制腳
- uchar T2Count;
- uint T0Count;
- uchar key,key_new,key_old,KeyPressTime;
- uchar status;
- uchar month,day,hour,min,sec,AlarmHr,AlarmMin;
- uchar LastDay;
- uchar AlmTime,AlmCount,DispTime;
- uchar CountHr,CountMin,CountSec,CountSetSta=0;
- uint year;
- bit TimeAdj,AlarmAdj,AlarmSta;
- bit adjust,DigiBit;
- //數碼管顯示代碼
- uchar code LedCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,
- 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x7f,
- 0x8e,0x89,0xc8,0xab,0xa3
- };
- uchar Disp[4];
- void LedScan(void);
- void KeyScan(void);
- void years(void);
- void date(void);
- void timer(void);
- void alarmClock(void);
- void CountDown(void);
- void ring(void);
- uchar DaysCount(void);
- void Init(void)
- {
- TH2=0x3c;TL2=0xb0;
- RCAP2H=0x3c;RCAP2L=0xb0;
- EA=1;ET2=1;
- TR2=1;
- TMOD=0x01;
- //TH0=0x3c;
- //TL0=0xb0;
- ET0=1;
- P1=0xff;
- year=2011;
- month=1;
- day=1;
- hour=0;
- min=0;
- status=2;
- buzzer=1;
- }
- /************主函數*************/
- void main(void)
- {
- Init();
- while(1)
- {
- KeyScan();
- LastDay=DaysCount();
- switch(status) //顯示狀態
- {
- case 0:years();break; //顯示年
- case 1:date();break; //顯示日期
- case 2:timer();break; //顯示時間
- case 3:alarmClock();break; //顯示鬧鐘時間
- case 4:CountDown();break; //顯示倒計時
- }
- LedScan();
- ring();
- }
- }
- /***************定時器T0中斷函數,用于倒計時**************/
- void timer0(void) interrupt 1 using 2
- {TH0=0x3c;
- TL0=0xb0;
- T0Count++;
- if(CountHr||CountMin||CountSec)
- {if(T0Count==20)
- {CountSec--;T0Count=0;}
- if(CountSec>=60)
- {CountSec=59;CountMin--;}
- if(CountMin>=60)
- {CountMin=59;CountHr--;}
- }
- if(T0Count==1200)
- {TR0=0;
- T0Count=0;
- }
- }
- /**************定時器T2中斷函數,用于計時**************/
- void timer2(void) interrupt 5 using 1
- {
- TF2=0;
- if(++T2Count==20)
- {sec++;T2Count=0;}
- if(!TimeAdj) //時間調整時,暫停計時
- {if(sec==60)
- {min++;sec=0;}
- if(min==60)
- {hour++;min=0;}
- if(hour==24)
- {day++;hour=0;}
- if(day>LastDay)
- {month++;day=1;}
- if(month>12)
- {year++;month=1;}
- }
- }
- void delay(uchar x)
- {
- uchar k;
- while(x--)
- for(k=0;k<123;k++);
- }
- /***********數碼管掃描顯示函數***************/
- void LedScan(void)
- {
- uchar i;
- uchar temp=0x08;
- for(i=0;i<4;i++)
- {
- P0=LedCode[Disp[i]]; //送段碼
- P2=~temp;temp>>=1; //LED顯示位控制
- delay(3); //延時
- P2=0xff; //關顯示
- }
- }
- /**********按鍵掃描程序***************/
- void KeyScan(void)
- {
- if((P1&0x0f)!=0x0f) //如果按下按鍵
- {if(KeyPressTime>0) //延時
- {
- switch(~(P1|0xf0)) //判斷鍵值
- {
- case 0x01:key_new=1;break;
- case 0x02:key_new=2;break;
- case 0x04:key_new=3;break;
- case 0x08:key_new=4;break;
- }
- }
- KeyPressTime++; //按鍵時間加1
- }
- else //如果沒有按鍵按下
- {key_new=0; //鍵值清零
- KeyPressTime=0; //按鍵時間清零
- }
- if(key_new!=key_old) //如果前后兩次鍵值不同
- {key=key_new; //鍵值等于本次鍵值
- }
- else //如果前后兩次鍵值相同(按住按鍵未釋放)
- {key=0; //鍵值清零
- if(KeyPressTime>100) //按鍵時間大于100,差不多1秒(作長按鍵處理)
- {KeyPressTime-=30; //按鍵時間減30,當累加到100再次動作,相當于300毫秒按鍵一次,
- key=key_new; //得到本次鍵值
- }
- }
- key_old=key_new; //記住本次鍵值
- }
- /***********計算本月有多少天**************/
- uchar DaysCount(void)
- {
- if(month==4||month==6||month==9||month==11) //4、6、9、11月為30天
- return 30;
- else if(month!=2) //1、3、5、7、8、10、12月為31天
- return 31;
- if(month==2)
- {if((year%4==0&&year%100!=0)||(year%400==0))
- return 29; //閏年2月為29天
- else
- return 28; //非閏年2月為28天
- }
- }
- /**************年函數**************/
- void years(void)
- {
- if(adjust) //設置,調整年
- {
- switch(key) //處理按鍵
- {case 1:{
- year++; //年加1
- break;
- }
- case 2:{
- year--; //年減1
- break;
- }
- case 3:{
- adjust=0; //退出設置
- DispTime=0;
- break;
- }
- }
- }
- else
- {
- if(key==2) status++; //顯示狀態加1,進入日期顯示
- if(key==3) adjust=1; //進入設置
- if(++DispTime==200) //顯示時間加1,系統默認顯示時間,通過按鍵切換其他顯示一段時間后自動返回時間顯示
- {status=2; //利用程序循環執行一次的時間作延時,每循環一次DispTime+1,加到200后退出返回時間顯示
- DispTime=0; //DispTime清零
- }
- }
- Disp[0]=year/1000; //年份千位
- Disp[1]=year/100%10; //年份百位
- Disp[2]=year/10%10; //年份十位
- Disp[3]=year%10; //年份個位
- if(T2Count<=10)
- {if(adjust) //如果調整年份,顯示閃爍
- Disp[0]=Disp[1]=Disp[2]=Disp[3]=DispOFF;
- }
- }
- /***********日期函數***************/
- void date(void)
- {
- if(adjust) //調整日期
- {
- switch(key)
- {case 1:{
- if(DigiBit==0) month++; //月加1
- else day++; //日加1
- if(month>12) month=1; //月大于12,月份等于1
- if(day>LastDay) day=1; //日大于本月最后一日,日等于1
- break;
- }
- case 2:{
- if(DigiBit==0) month--; //月減1
- else day--; //日減1
- if(month==0) month=12; //月=0,月份=12
- if(day==0) day=LastDay; //日=0,日等于本月最后一天
- break;
- }
- case 3:{
- DigiBit=~DigiBit; //月、日設置選擇切換
- if(DigiBit==0) //DigiBit=0 選擇月 DigiBit=1 選擇日
- {adjust=0;
- DispTime=0;
- }
- break;
- }
- }
- }
- else
- {
- if(key==1) {status--;DispTime=0;} //顯示年,顯示時間清零重新計算
- if(key==2) status++; //顯示時間
- if(key==3) adjust=1; //進入設置
- if(++DispTime==200) //顯示時間到,返回時間顯示
- {status=2;
- DispTime=0;
- }
- }
- Disp[0]=month/10;
- Disp[1]=month%10;
- Disp[2]=day/10;
- Disp[3]=day%10+11;
- if(T2Count<=10)
- {if(adjust)
- {
- if(!DigiBit) //如果調整日,日顯示閃爍
- {
- Disp[0]=DispOFF;
- Disp[1]=DispOFF;
- }
- else //如果調整月,月顯示閃爍
- {
- Disp[2]=DispOFF;
- Disp[3]=POINT;
- }
- }
- }
- }
- /**************時間函數****************/
- void timer(void)
- {
- if(TimeAdj) //調整時間
- {
- switch(key)
- {case 1:{ //up/加 按鍵
- if(DigiBit==0) hour++; //根據按鍵選擇時間、分鐘加調整
- else min++;
- if(hour==24) hour=0;
- if(min==60) min=0;
- break;
- }
- case 2:{ //down 減 按鍵
- if(DigiBit==0) hour--; //時間、分鐘減調整
- else min--;
- if(hour>=24) hour=23;
- if(min>=60) min=59;
- break;
- }
- case 3:{
- DigiBit=~DigiBit; //DigiBit=0 小時,DigiBit=1 分鐘
- if(DigiBit==0) //時間設置完后,秒清零,定時器重新計時
- {sec=0;
- TR2=0;
- TH2=0x3c;TL2=0xb0;
- T2Count=0;
- TR2=1;
- TimeAdj=0;
- }
- break;
- }
- }
- }
- else
- {
- if(key==1) {status--;DispTime=0;}
- if(key==2) {status++;DispTime=80;}//進入鬧鐘顯示,顯示時間初始值為80
- if(key==3) TimeAdj=1;
- }
- Disp[0]=hour/10;
- Disp[1]=hour%10;
- Disp[2]=min/10+11;
- Disp[3]=min%10+11;
- if(T2Count<=10)
- {if(TimeAdj)
- {
- if(!DigiBit)
- {
- Disp[0]=DispOFF;
- Disp[1]=DispOFF;
- }
- else
- {
- Disp[2]=POINT;
- Disp[3]=POINT;
- }
- }
- else
- {
- Disp[2]=min/10;
- Disp[3]=min%10;
- }
- }
- }
- /*************鬧鐘函數***************/
- void alarmClock(void)
- {Disp[0]=AlarmHr/10;
- Disp[1]=AlarmHr%10;
- Disp[2]=AlarmMin/10+11;
- Disp[3]=AlarmMin%10+11;
- if(DispTime<80)//顯示時間<80,顯示鬧鐘開關狀態,顯示時間>=80,顯示鬧鐘時間
- {if(AlarmSta)
- {Disp[0]=DispOFF;
- Disp[1]=DispOFF;
- Disp[2]=O;
- Disp[3]=N;
- }
- else
- {Disp[0]=DispOFF;
- Disp[1]=O;
- Disp[2]=F;
- Disp[3]=F;
- }
- }
- if(AlarmAdj)//設置鬧鐘時間
- {
- switch(key)
- {case 1:{
- if(DigiBit==0) AlarmHr++;
- else AlarmMin++;
- if(AlarmHr==24) AlarmHr=0;
- if(AlarmMin==60) AlarmMin=0;
- break;
- }
- case 2:{
- if(DigiBit==0) AlarmHr--;
- else AlarmMin--;
- if(AlarmHr>=24) AlarmHr=23;
- if(AlarmMin>=60) AlarmMin=59;
- break;
- }
- case 3:{
- DigiBit=~DigiBit;
- if(DigiBit==0)
- {AlarmAdj=0;
- DispTime=80;
- }
- break;
- }
- }
- if(T2Count<=10)
- {
- if(!DigiBit)
- {
- Disp[0]=DispOFF;
- Disp[1]=DispOFF;
- }
- else
- {
- Disp[2]=POINT;
- Disp[3]=POINT;
- }
- }
- }
- else
- {
- if(key==1) status--;
- if(key==2)
- {status++;
- DispTime=0;
- }
- if(key==3) AlarmAdj=1;
- if(key==4)//鬧鐘開關按鍵
- {if(DispTime<80) //初次按下,顯示上次設置狀態
- AlarmSta=~AlarmSta; //再按可改變設置
- DispTime=0;//每按一次,顯示時間清零,顯示鬧鐘開關狀態
- }
- DispTime++;
- if(DispTime==255)
- {status=2;
- DispTime=0;
- }
- }
- }
- /**************倒計時函數*****************/
- void CountDown(void)
- {
- if(adjust)//設置倒數時間
- {
- switch(CountSetSta)
- {case 0:{//設置倒數小時
- if(key==1) CountHr++;
- if(key==2) CountHr--;
- if(key==3) CountSetSta++;
- if(CountHr==100) CountHr=0;
- if(CountHr>100) CountHr=99;
- Disp[0]=H;
- Disp[1]=DispOFF;
- Disp[2]=CountHr/10;
- Disp[3]=CountHr%10;
- break;
- }
- case 1:{//設置倒數分鐘
- if(key==1) CountMin++;
- if(key==2) CountMin--;
- if(key==3) CountSetSta++;
- if(CountMin==60) CountMin=0;
- if(CountMin>60) CountMin=59;
- Disp[0]=M;
- Disp[1]=DispOFF;
- Disp[2]=CountMin/10;
- Disp[3]=CountMin%10;
- break;
- }
- case 2:{//設置倒數秒
- if(key==1) CountSec++;
- if(key==2) CountSec--;
- if(key==3) //設置鍵
- {if(CountHr||CountMin||CountSec)//設置完成后,若倒數的時、分、秒不為零,倒計時開始
- {TH0=0x3c; TL0=0xb0;
- T0Count=0;
- TR0=1;
- }
- CountSetSta=0;
- adjust=0;
- DispTime=0;
- }
- if(CountSec==60) CountSec=0;
- if(CountSec>60) CountSec=59;
- Disp[0]=5;
- Disp[1]=DispOFF;
- Disp[2]=CountSec/10;
- Disp[3]=CountSec%10;
- break;
- }
- }
- }
- else
- {
- if(key==1) //進入鬧鐘顯示
- {status--;
- DispTime=80;
- }
- if(key==3) //設置倒數時間
- {
- TR0=0;
- CountHr=CountMin=CountSec=0;
- adjust=1;
- }
- if(key==4) //停止倒計時
- {TR0=0;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
單片機數碼管時鐘.rar
(29.23 KB, 下載次數: 298)
2018-10-15 21:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|