要求
顯示當前時間與日期。
手動修改時間、日期信息,修改該位信息時該數碼管閃爍。
手動開啟/關閉鬧鐘功能,而且有鬧鐘狀態指示燈。
手動設置鬧鐘,而且當達到設置好的時間點時報警,報警時長為5s。
分析
萬年歷的整體設計如圖所示:
0.png (16.94 KB, 下載次數: 45)
下載附件
2019-1-20 01:22 上傳
51單片機核心模塊包括51單片機最小系統模塊,是設計應用的控制核心;顯示模塊用于顯示時間與日期、設計鬧鐘時間等信息;指示燈包括時間日期暫停計數指示燈和鬧鐘開啟或關閉狀態指示燈;鬧鐘采用蜂鳴器發出聲音警報;鍵盤輸入模塊用來設置和切換時間、日期,開啟或關閉鬧鐘,設置鬧鐘時間等。
制作出來的實物圖如下:
0.jpg (55.31 KB, 下載次數: 38)
下載附件
2019-1-20 01:24 上傳
可用安卓接口5V供電,也可接學生電源或兩個3.7V的電池通過LM7805穩壓管供電。
功能介紹: 程序初始化處于時間計數狀態(已設置初始值為12:12:00),按下Key2選擇位校準位,按下第一次選中秒鐘,第二次選中分鐘,第三次選中時鐘,第四次退出校時功能,被選中位不斷閃爍,并且按下Key3可進行被選擇位逐漸加一,實現校時。按下Key4,數碼管顯示界面跳轉為日期顯示,按下按鍵Key2和Key3 可實現與時間同一校準時間的功能,再次按下Key4切換為時間界面。在時間顯示或者日期顯示狀態下,按下按鍵Key1可獨立暫停時間計數或日期的增加,并且LED1指示燈亮。 按下按鍵K3開啟鬧鐘功能,LED2亮,再次按下則關閉鬧鐘,LED2滅。按下K4切換為鬧鐘設置狀態(已設置鬧鐘初始值為12:12:00),按下K1進行分鐘位加一,按下Key2切換為時鐘位調時,按下K1進行時鐘位加一,在鬧鐘狀態下秒鐘不可調。在進入鬧鐘設置功能前,需先開啟鬧鐘功能,否則鬧鐘不會到點鬧鈴。按下K2退出鬧鐘設置界面,等到實時時間與所設置鬧鐘時間一致時,蜂鳴器響5s鐘,中途可按下K3關閉蜂鳴器,并且關閉鬧鐘功能。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
截圖20190119195459.png (111.88 KB, 下載次數: 55)
下載附件
2019-1-19 20:14 上傳
0.png (9.67 KB, 下載次數: 53)
下載附件
2019-1-20 01:03 上傳
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
0.png (56 KB, 下載次數: 45)
下載附件
2019-1-20 01:17 上傳
0.png (54.17 KB, 下載次數: 39)
下載附件
2019-1-20 01:17 上傳
0.png (5.41 KB, 下載次數: 39)
下載附件
2019-1-20 01:17 上傳
程序流程圖:
0.png (24.29 KB, 下載次數: 42)
下載附件
2019-1-20 01:25 上傳
單片機源程序如下:
- #include<reg51.h>
- #define uChar unsigned char
- #define uInt unsigned int
- uChar a[]={~0x3f,~0x06,~0x5b,~0x4f,~0x66,~0x6d,~0x7d,~0x07,~0x7f,~0x6f}; //數碼管段選碼,0——9
- uChar b[]={~0xfe,~0xfd,~0xfb,~0xf7,~0xef,~0xdf,~0xbf,~0x7f}; //數碼管位選碼,高——低
- uChar second=0,minute=12,hour=12,month=1,day=13,count; uInt year=2019;
- uChar f_nao=12,s_nao=12; //鬧鐘分計數,鬧鐘時計數
- uChar wave=0; //定時器1對0.1ms定時時間進行計數,控制蜂鳴器響的頻率
- bit flag_nao; //控制鬧鐘開關變量 flag_nao= 0-off;1--on
- sbit K1 = P3^0; //設置鬧鐘分/時位加一
- sbit K2 = P3^1; //退出設置鬧鐘
- sbit K3 = P3^2; //鬧鐘開關
- sbit K4 = P3^3; //進入設置鬧鐘狀態
- sbit Key1 = P3^4; //計時停止
- sbit Key2 = P3^5; //調位(校準)
- sbit Key3 = P3^6; //所調位加一
- sbit Key4 = P3^7; //切換時-分-秒、年-月-日
- sbit BEEP = P2^2; //蜂鳴器端口
- sbit LED1 = P2^0; //計時停止時LED1亮
- sbit LED2 = P2^1; //鬧鐘開啟時LED2亮
-
- //函數聲明
- void Delayms(uInt t); //長延時函數
- void Dispaly1(uChar second,uChar minute,uChar hour); //時-分-秒顯示
- void Dispaly2(uChar day,uChar month,uInt year); //年-月-日顯示
- void Keyscan1(); //按鍵Key4按下次數為雙數時(按鍵Key1~3控制時-分-秒)
- void Keyscan2(); //按鍵Key4按下次數為單數時(按鍵Key1~3控制年-月-日)
- void nao_judge(); //判斷鬧鐘
-
- /*************時-分-秒、年-月-日閃爍函數聲明*********************/
- void delay(uInt t); /***/
- void Bright1(uChar second,uChar minute,uChar hour); /***/
- void Hour_flicker(uChar second,uChar minute,uChar hour); /***/
- void Minute_flicker(uChar second,uChar minute,uChar hour); /***/
- void Second_flicker(uChar second,uChar minute,uChar hour); /***/
- void Bright2(uChar day,uChar month,uInt year); /***/
- void Year_flicker(uChar day,uChar month,uInt year); /***/
- void Month_flicker(uChar day,uChar month,uInt year); /***/
- void Day_flicker(uChar day,uChar month,uInt year); /***/
- /*************時-分-秒、年-月-日閃爍函數聲明*********************/
- //主函數
- void main()
- {
- TMOD=0x11; //置T0、T1都為工作方式1
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- TR0=1; //開啟T0
- ET0=1; //打開T0中斷允許位
- IT1=1; //設置外部中斷1為下降沿觸發
- IT0=0; //設置外部中斷0為低電平觸發
- EX1=1; //打開外部中斷1允許位
- EX0=1; //打開外部中斷0允許位
- PT0=1; //設置內部定時中斷優先級大于外部中斷優先級
- EA=1; //打開中斷總允許位
- BEEP=1;
- flag_nao=0;
- while(1)
- {
- static uChar h=0;
- nao_judge();
- if(Key4==0)
- {
- Delayms(10);
- if(Key4==0)
- while(!Key4); //空操作,等待按鍵釋放
- h++;
- }
- if(h%2==1)
- {
- Dispaly2(day,month,year);
- Keyscan2();
- }
- if(h%2==0)
- {
- Dispaly1(second,minute,hour);
- nao_judge();
- Keyscan1();
- }
- }
- }
- //長延時函數
- void Delayms(uInt t)
- {
- uInt i,j;
- for(i=0;i<t;i++)
- for(j=0;j<125;j++)
- ;
- }
- //時-分-秒顯示
- void Dispaly1(uChar second,uChar minute,uChar hour)
- {
- P0=b[0];
- P1=a[hour/10];
- Delayms(1);
- P1=0xff;
- P0=b[1];
- P1=a[hour%10];
- Delayms(1);
- P1=0xff;
- P0=b[2];
- P1=0xbf;
- Delayms(1);
- P1=0xff;
- P0=b[3];
- P1=a[minute/10];
- Delayms(1);
- P1=0xff;
- P0=b[4];
- P1=a[minute%10];
- Delayms(1);
- P1=0xff;
- P0=b[5];
- P1=0xbf;
- Delayms(1);
- P1=0xff;
- P0=b[6];
- P1=a[second/10];
- Delayms(1);
- P1=0xff;
- P0=b[7];
- P1=a[second%10];
- Delayms(1);
- P1=0xff;
- }
- //年-月-日顯示
- void Dispaly2(uChar day,uChar month,uInt year)
- {
- P0=b[7];
- P1=a[day%10];
- Delayms(1);
- P1=0xff;
- P0=b[6];
- P1=a[day/10];
- Delayms(1);
- P1=0xff;
- P0=b[5];
- P1=a[month%10]&0x7f;
- Delayms(1);
- P1=0xff;
- P0=b[4];
- P1=a[month/10];
- Delayms(1);
- P1=0xff;
- P0=b[3];
- P1=a[year%10]&0x7f;
- Delayms(1);
- P1=0xff;
- P0=b[2];
- P1=a[(year%100)/10];
- Delayms(1);
- P1=0xff;
- P0=b[1];
- P1=a[(year/100)%10];
- Delayms(1);
- P1=0xff;
- P0=b[0];
- P1=a[(year/1000)];
- Delayms(1);
- P1=0xff;
- }
- //按鍵Key4按下次數為雙數時(控制時-分-秒),按鍵Key1~3的控制
- void Keyscan1()
- {
- static uChar i=0,j=0; //static-保存變量數據,不會清零
- if(Key1==0)
- {
- Delayms(10); //消抖
- if(Key1==0)
- while(!Key1); //等待按鍵彈起
- i++;
- }
- if(i%2==1) //若Key1按下次數為單數時,停止計數
- {
- LED1=0;
- TR0=0;
- }
- if(i%2==0) //若Key1按下次數為雙數時,開始計數
- {
- LED1=1;
- TR0=1;
- }
-
- if(Key2==0) //按鍵Key2選擇調位
- {
- Delayms(10);
- if(Key2==0)
- while(!Key2);
- j++;
- }
- if(j%4==1) //按鍵按下一次
- {
- Second_flicker(second,minute,hour); //秒顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0) //按鍵Key3進行選定位加一
- while(!Key3);
- second++;
- if(second==60)
- second=0;
- }
- }
- if(j%4==2)//按鍵按下兩次
- {
- Minute_flicker(second,minute,hour); //分顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0)
- while(!Key3);
- minute++;
- if(minute==60)
- minute=0;
- }
- }
- if(j%4==3)//按鍵按下三次
- {
- Hour_flicker(second,minute,hour); //時顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0)
- while(!Key3);
- hour++;
- if(hour==24)
- hour=0;
- }
- }
- }
- //按鍵Key4按下次數為單數時(控制年-月-日),按鍵Key1~3的控制
- void Keyscan2()
- {
- static uChar m=0,n=0;
- if(Key1==0)
- {
- Delayms(10);
- if(Key1==0)
- while(!Key3);
- m++;
- }
- if(m%2==1)
- {
- LED1=0;
- TR0=0;
- }
- if(m%2==0)
- {
- LED1=1;
- TR0=1;
- }
- if(Key2==0)
- {
- Delayms(10);
- if(Key2==0)
- while(!Key2);
- n++;
- }
- if(n%4==1)
- {
- Day_flicker(day,month,year); //日顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0)
- while(!Key3);
- day++;
- if(day==32)
- day=1;
- }
- }
- if(n%4==2)
- {
- Month_flicker(day,month,year); //月顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0)
- while(!Key3);
- month++;
- if(month==13)
- month=1;
- }
- }
- if(n%4==3)
- {
- Year_flicker(day,month,year); //年顯示位閃爍
- if(Key3==0)
- {
- Delayms(10);
- if(Key3==0)
- while(!Key3);
- year++;
- if(year==10000)
- year=0;
- }
- }
- }
- //判斷鬧鐘,當時間和設置鬧鐘時間相等時,鬧鈴響5S
- void nao_judge()
- {
- if(flag_nao==1) //如果flag_nao為真,鬧鐘開啟
- {
- if((minute==f_nao)&&(hour==s_nao)) //判斷實時時間和鬧鐘時間的分、時是否同時相等
- {
- while(second<5&&flag_nao) //如果second<=5和flag_nao都為真,鬧鈴響5s
- {
- BEEP=0; //TR1=1; //開啟T0
- Dispaly1(second,minute,hour);
- }
- }
- }
- BEEP=1;
- }
- //定時器中斷0,時鐘計數(不斷執行)
- void time0_int(void) interrupt 1
- {
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- count++;
- if(count==100)
- {
- count=0;
- second++;
- if(second==60)
- {
- second=0;
- minute++;
- if(minute==60)
- {
- minute=0;
- hour++;
- if(hour==24)
- {
- hour=0;
- day++;
- if(day==32)
- {
- day=1;
- month++;
- if(month==13)
- {
- month=1;
- year++;
- if(year==10000)
- {
- year=0;
- }
- }
- }
- }
- }
- }
- }
- }
- //外部中斷0,鬧鐘開關,控制flag_nao,按下K3關閉鬧鐘
- void guan_naozhong() interrupt 0
- {
- flag_nao=~flag_nao;
- LED2=~LED2;
- TR1 = 0; //K3按下,開啟外部中斷0,關閉定時器中斷1,鬧鐘停止響鈴
- while(!K3)
- Dispaly1(second,minute,hour);
- }
- //外部中斷1,調節鬧鐘時間
- void naozhong() interrupt 2
- {
- static uChar n=0;
- // s_nao=12; //設置鬧鐘時鐘初始值
- // f_nao=31; //設置鬧鐘分鐘初始值
- while(K2) //等待按下K2退出,否則循環執行鬧鐘時間設置
- {
- Dispaly1(0,f_nao,s_nao); //顯示鬧鐘設置
- if(Key2==0) //鬧鐘調位調時鐘、分鐘
- {
- Delayms(10);
- if(Key2==0)
- while(!Key2);
- n++;
- }
- if(n%2==1) //調節鬧鐘時鐘
- {
- if(K1==0)
- {
- Dispaly1(0,f_nao,s_nao);
- if(K1==0)
- {
- if(s_nao==23)
- s_nao=0;
- else s_nao++;
- }
- while(!K1)
- Dispaly1(0,f_nao,s_nao);
- }
- }
- if(n%2==0) //調節鬧鐘分鐘
- {
- if(K1==0)
- {
- Dispaly1(0,f_nao,s_nao);
- if(K1==0)
- {
- if(f_nao==59)
- f_nao=0;
- else f_nao++;
- }
- while(!K1)
- Dispaly1(0,f_nao,s_nao);
- }
- }
- }
- }
-
- /************************************************/
- /****************調位時選擇位閃爍****************/
- /************************************************/
- //短延時
- void delay(uInt t)
- {
- uInt i;
- for(i=0;i<t;i++)
- ;
- }
- //數碼管0~7位分別顯示時-分-秒
- void Bright1(uChar second,uChar minute,uChar hour)
- {
- uChar p,k=10;
- for(p=0;p<50;p++)
- {
- P0=b[0];
- P1=a[hour/10];
- delay(k);
- P1=0xff;
- P0=b[1];
- P1=a[hour%10];
- delay(k);
- P1=0xff;
- P0=b[2];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[3];
- P1=a[minute/10];
- delay(k);
- P1=0xff;
- P0=b[4];
- P1=a[minute%10];
- delay(k);
- P1=0xff;
- P0=b[5];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[6];
- P1=a[second/10];
- delay(k);
- P1=0xff;
- P0=b[7];
- P1=a[second%10];
- delay(k);
- P1=0xff;
- }
- }
- //秒顯示位閃爍
- void Second_flicker(uChar second,uChar minute,uChar hour)
- {
- uChar p,k=10;
- Bright1(second,minute,hour);
- for(p=0;p<50;p++)
- {
- P0=b[0];
- P1=a[hour/10];
- delay(k);
- P1=0xff;
- P0=b[1];
- P1=a[hour%10];
- delay(k);
- P1=0xff;
- P0=b[2];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[3];
- P1=a[minute/10];
- delay(k);
- P1=0xff;
- P0=b[4];
- P1=a[minute%10];
- delay(k);
- P1=0xff;
- P0=b[5];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[6]; //該位數碼管滅
- P1=0xff;
- delay(k);
- P0=b[7]; //該位數碼管滅
- P1=0xff;
- delay(k);
- }
- }
- //分顯示位閃爍
- void Minute_flicker(uChar second,uChar minute,uChar hour)
- {
- uChar p,k=10;
- Bright1(second,minute,hour);
- for(p=0;p<50;p++)
- {
- P0=b[0];
- P1=a[hour/10];
- delay(k);
- P1=0xff;
- P0=b[1];
- P1=a[hour%10];
- delay(k);
- P1=0xff;
- P0=b[2];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[3]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[4]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[5];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[6];
- P1=a[second/10];
- delay(k);
- P1=0xff;
- P0=b[7];
- P1=a[second%10];
- delay(k);
- P1=0xff;
- }
- }
- //時顯示位閃爍
- void Hour_flicker(uChar second,uChar minute,uChar hour)
- {
- uChar p,k=10;
- Bright1(second,minute,hour);
- for(p=0;p<50;p++)
- {
- P0=b[0]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[1]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[2];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[3];
- P1=a[minute/10];
- delay(k);
- P1=0xff;
- P0=b[4];
- P1=a[minute%10];
- delay(k);
- P1=0xff;
- P0=b[5];
- P1=0xbf;
- delay(k);
- P1=0xff;
- P0=b[6];
- P1=a[second/10];
- delay(k);
- P1=0xff;
- P0=b[7];
- P1=a[second%10];
- delay(k);
- P1=0xff;
- }
- }
- //數碼管0~7位分別顯示年-月-日
- void Bright2(uChar day,uChar month,uInt year)
- {
- uChar p,k=10;
- for(p=0;p<50;p++)
- {
- P0=b[7];
- P1=a[day%10];
- delay(k);
- P1=0xff;
- P0=b[6];
- P1=a[day/10];
- delay(k);
- P1=0xff;
- P0=b[5];
- P1=a[month%10]&0x7f;
- delay(k);
- P1=0xff;
- P0=b[4];
- P1=a[month/10];
- delay(k);
- P1=0xff;
- P0=b[3];
- P1=a[year%10]&0x7f;
- delay(k);
- P1=0xff;
- P0=b[2];
- P1=a[(year%100)/10];
- delay(k);
- P1=0xff;
- P0=b[1];
- P1=a[(year/100)%10];
- delay(k);
- P1=0xff;
- P0=b[0];
- P1=a[(year/1000)];
- delay(k);
- P1=0xff;
- }
- }
- //日顯示位閃爍
- void Day_flicker(uChar day,uChar month,uInt year)
- {
- uChar p,k=10;
- Bright2(day,month,year);
- for(p=0;p<50;p++)
- {
- P0=b[7]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[6]; ////熄滅
- P1=0xff;
- delay(k);
- P0=b[5];
- P1=a[month%10]&0x7f;
- delay(k);
- P1=0xff;
- P0=b[4];
- P1=a[month/10];
- delay(k);
- P1=0xff;
- P0=b[3];
- P1=a[year%10]&0x7f;
- delay(k);
- P1=0xff;
- P0=b[2];
- P1=a[(year%100)/10];
- delay(k);
- P1=0xff;
- P0=b[1];
- P1=a[(year/100)%10];
- delay(k);
- P1=0xff;
- P0=b[0];
- P1=a[(year/1000)];
- delay(k);
- P1=0xff;
- }
- }
- //月顯示位閃爍
- void Month_flicker(uChar day,uChar month,uInt year)
- {
- uChar p,k=10;
- Bright2(day,month,year);
- for(p=0;p<50;p++)
- {
- P0=b[7];
- P1=a[day%10];
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
萬年歷-原理圖 功能介紹 程序 PCB.zip
(14.17 MB, 下載次數: 158)
2019-1-19 20:18 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|