單片機(jī)實(shí)驗(yàn)要求如下
合理使用STC單片機(jī)內(nèi)的定時(shí)器資源,并使用1602實(shí)現(xiàn)數(shù)字鐘的功能,顯示方式xx:xx:xx(時(shí):分:秒) 基本部分: 能在1602上以xx:xx:xx的形式顯示時(shí)間,符合真實(shí)工作情況(40分) 提高部分: (1)能通過(guò)一個(gè)按鍵將1602切換到顯示年月日,顯示格式xx/xx/xx(年/月/日)(20分), (2)通過(guò)按鍵可以調(diào)整時(shí)、分、秒(30分) 發(fā)揮部分: 完善電子鐘的功能(10分) 注: (1)設(shè)計(jì)的電子鐘,使用最少的按鍵,按照電子表,對(duì)多使用3個(gè)按鍵。 (2)時(shí)鐘工作時(shí),其進(jìn)位應(yīng)該與真實(shí)的電子鐘相同。 (3)顯示時(shí)間和顯示年月日之間的進(jìn)位關(guān)系符合實(shí)際。
【思路】
(一)使用定時(shí)器0產(chǎn)生1秒的時(shí)鐘信號(hào),用來(lái)時(shí)鐘走時(shí),并達(dá)到24小時(shí)候進(jìn)位到日期中的日,進(jìn)而是月,年。通過(guò)if條件語(yǔ)句實(shí)現(xiàn)了瑞年的處理,月份天數(shù)不一致的處理。
(二)總共使用了兩個(gè)按鍵。通過(guò)外部中斷0,切換到顯示日期,并且記錄外部中斷0觸發(fā)的次數(shù),通過(guò)次數(shù)進(jìn)入調(diào)整狀態(tài),時(shí)間和日期均可以調(diào)整。通過(guò)外部中斷0進(jìn)入調(diào)整狀態(tài)后,再通過(guò)外部中斷1調(diào)整時(shí)間和日期,日期和時(shí)間的調(diào)整采用了加滿溢出的方式。在日期的調(diào)整過(guò)程中,不會(huì)出現(xiàn)13月 35日等非正常邏輯的顯示結(jié)果。
(三)完善電子鐘的部分,日期也可以調(diào)整,整點(diǎn)報(bào)時(shí)(由于板子上沒有蜂鳴器,采用了兩個(gè)LED表示)。
【運(yùn)行說(shuō)明】 (1)進(jìn)入時(shí)間顯示狀態(tài),默認(rèn)值為00:00:00 (2)通過(guò)外部中斷0進(jìn)入日期顯示狀態(tài),默認(rèn)值為2019/05/26。 (3)再次按下外部中斷0進(jìn)入時(shí)間調(diào)整狀態(tài),修改時(shí)間的小時(shí)的十位,并通過(guò)在第二行的^作為修改位標(biāo)志。 (4)之后類似,此步展示日期修改的年的個(gè)位。 (5)完成所有的調(diào)整后,再次按下外部中斷0,會(huì)再次進(jìn)入時(shí)間的顯示狀態(tài)。 【答題過(guò)程遇到的問(wèn)題說(shuō)明】 (1)調(diào)整的部分,如果代碼放的位置不合適,調(diào)表會(huì)有不合理的現(xiàn)象發(fā)生,并且需要將調(diào)表所用的外部中斷1優(yōu)先級(jí)大于定時(shí)器中斷。 (2)嘗試過(guò)用閃爍和光標(biāo)作為修改位的指示,但是很容易發(fā)生混亂,就采用了在第二行,用合適的字符指示修改的位。 (3)最初的想法,是想調(diào)用矩陣鍵盤的兩個(gè)鍵作為加減,后來(lái)在調(diào)試的過(guò)程中,發(fā)現(xiàn)有干擾,因?yàn)長(zhǎng)CD1602和矩陣鍵盤都用到了P0口,所以當(dāng)矩陣鍵盤被按下的時(shí)候,會(huì)對(duì)1602的顯示造成干擾,所以之后的方案,取消了減,只采用了兩個(gè)外部中斷的按鍵。 (4)為了使時(shí)間和日期的顯示和調(diào)整符合真正的電子鐘,要花費(fèi)一定的精力調(diào)整代碼。 【源代碼及注釋】 注:文檔中的代碼只有主程序main.c,別的頭文件及.c文件在工程文件夾內(nèi)。
單片機(jī)源程序如下:
- #include "reg51.h"
- #include "led1602.h"
- #define uchar unsigned char
- #define uint unsigned int
- sfr P4=0xc0;
- int year=2019;//初始顯示日期的年
- uchar month=05,day=26,sec = 0, min = 0, hou = 0;//初始顯示日期為 2019年05月26日,初始顯示時(shí)間為00:00:00
- uchar num = 0;//調(diào)整日期和時(shí)間,以及切換顯示日期和時(shí)間的標(biāo)志位
- uchar time = 0;//一秒的時(shí)間信號(hào)
- uchar jia=0;//調(diào)整日期和時(shí)間的信號(hào)
- sbit P46=P4^6;//鬧鐘(整點(diǎn)報(bào)時(shí))的兩個(gè)燈
- sbit P47=P4^7;
- void time_rec();//時(shí)鐘走時(shí)函數(shù)
- void init();//程序初始化函數(shù),包括LCD的初始化,中斷的設(shè)置,定時(shí)器的TH TL設(shè)置
- void write_liangwei(uchar add,uchar date);//兩位字符分離函數(shù)
- void write_siwei(uchar add1,int date1);//四位字符分離函數(shù)
- void show_time();//時(shí)間顯示函數(shù)
- void show_dat();//日期顯示函數(shù)
- void main()
- {
- init();
- while(1){
- time_rec();//調(diào)用時(shí)鐘走時(shí)函數(shù)
- if(num == 0)//顯示時(shí)間
- {
- lcdshowstr(0,1," ");
- show_time();
- }
- if(num==1)//顯示日期
- {
- lcdshowstr(0,1," ");
- show_dat();
- jia = 0;
- }
- if(num == 2)//顯示時(shí)間的同時(shí),修改時(shí)間的小時(shí)的十位
- {
- lcdshowstr(0,1,"^");
- show_time();
- jia = 0;
- }
- if(num == 3)//顯示時(shí)間的同時(shí),修改時(shí)間的小時(shí)的個(gè)位,以下類似
- {
- lcdshowstr(0,1," ^");
- show_time();
- jia = 0;
- }
- if(num == 4)
- {
- lcdshowstr(0,1," ^");
- show_time();
- jia = 0;
- }
- if(num == 5)
- {
- lcdshowstr(0,1," ^");
- show_time();
- jia = 0;
- }
- if(num == 6)
- {
- lcdshowstr(0,1," ^");
- show_time();
- jia = 0;
- }
- if(num == 7)
- {
- lcdshowstr(0,1," ^");
- show_time();
- jia = 0;
- }
- if(num == 8)
- {
- lcdshowstr(0,1,"^ ");
- show_dat();
- jia = 0;
- }
- if(num == 9)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 10)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 11)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 12)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 13)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 14)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- if(num == 15)
- {
- lcdshowstr(0,1," ^ ");
- show_dat();
- jia = 0;
- }
- }
- }
- void zhuangtai() interrupt 0 //外部中斷0 用于校準(zhǔn)時(shí)間在時(shí)、分、秒之間進(jìn)行切換
- {
- num = num + 1;
- if(num == 16)
- {
- num = 0;
- }
- }
- void timer0() interrupt 1 //定時(shí)器0的中斷子函數(shù) 用來(lái)產(chǎn)生1秒的時(shí)間,用于時(shí)鐘走時(shí)
- {
- TH0 = 0x3C;
- TL0 = 0xB0;
- time++;
- if(time == 20)
- {
- sec++;
- time = 0;
- }
- }
- void jiaozhun() interrupt 2 //外部中斷1用來(lái)調(diào)整時(shí)間、日期
- {
- jia = 1;
- if(num == 2)
- {
- hou = hou + 10;
- if((hou%10<4)&&hou>24)
- {
- hou = hou - 30;
- }
- if((hou%10>4)&&hou>24)
- {
- hou = hou - 20;
- }
- if(hou==24)
- {
- hou = hou - 20;
- }
- }
- if(num==3)
- {
- hou = hou + 1;
- if(hou>23)
- hou = 0;
- }
- if(num==4)
- {
- min = min+10 ;
- if(min > 59)
- {
- min = min -60;
- }
- }
- if(num==5)
- {
- min= min+1;
- if(min>59)
- {
- min = 0;
- }
- }
- if(num==6 )
- {
- sec=sec + 10;
- if(sec >59 )
- {
- sec = sec - 60;
- }
- }
- if(num==7)
- {
- sec= sec+1;
- if(sec>59)
- {
- sec = 0;
- }
- }
- if(num==8)
- {
- year= year+1000;
- if(year>9000)
- {
- year = year -10000;
- }
- }
- if(num==9)
- {
- year=year+100;
- if(year%1000/100>9)
- {
- year = year - 1000;
- }
- }
- if(num==10)
- {
- year=year+10;
- if(year%100/10>9)
- {
- year = year -100;
- }
- }
- if(num==11)
- {
- year=year+1;
- if(year%10>9)
- {
- year = year - 10;
- }
- }
- if(num==12)
- {
- month = month +10;
- if((month%10<2)&&month>12)
- {
- month = month - 20;
- }
- if((month%10>2)&&month>12)
- {
- month = month - 10;
- }
- if(month==12)
- {
- month = month - 10;
- }
- }
- if(num==13)
- {
- month = month +1;
- if(month%10>9)
- {
- month = 0;
- }
- if(month==12)
- {
- month = 0;
- }
- }
- if(num==14)
- {
- day = day +10;
- if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
- {
- if((day%10<1)&&day>31)
- {
- day = day - 40;
- }
- if((day%10>1)&&day>31)
- {
- day = day - 30;
- }
- if(day==31)
- {
- day = 0;
- }
- }
- if(month==4||month==6||month==9||month==11)
- {
- if(day>30)
- {
- day = day - 40;
- }
- }
- if(((year%4==0&&year%100!=0)||(year%400==0))&&month==2)
- {
- if(day>29)
- {
- day = day - 30;
- }
- }
- if(year%4!=0&&month==2)
- {
- if(day>28)
- {
- day = day -30;
- }
- }
- }
- if(num==15)
- {
- day = day +1;
- if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day>31)
- {
- day = 0;
- }
- if((month==4||month==6||month==9||month==11)&&day>30)
- {
- day = 0;
- }
- if(((year%4==0&&year%100!=0)||(year%400==0))&&day>29)
- {
- day = 0;
- }
- if((year%4!=0)&&day>28)
- {
- day = 0;
- }
- }
- }
- /*
- *時(shí)間走時(shí)函數(shù),計(jì)滿24小時(shí)后,日加一
- *并且設(shè)置了整點(diǎn)報(bào)時(shí),或者說(shuō)鬧鐘功能
- *由于單片機(jī)沒有蜂鳴器,采用兩個(gè)LED作為表示
- *LED亮一分鐘后自動(dòng)熄滅
- */
- void time_rec()
- {
- if(sec == 60)
- {
- P46 = 1;
- P47 = 1;
- sec = 0;
- min ++;
- if(min ==60)
- {
- P46 = 0;
- P47 = 0;
- min = 0;
- hou++;
- if(hou==24)
- {
- hou = 0;
- day++;
- if((year%4==0&&year%100!=0)||(year%400==0))//判斷是否為閏年的2月
- {
- if(day==30)
- {
- day=0;
- month++;
- if(month==13)
- {
- month=0;
- year++;
- }
- }
- }
- if(year%4!=0&&month==2)
- {
- if(day==29)
- {
- day=0;
- month++;
- if(month==13)
- {
- month=0;
- year++;
- }
- }
- }
- if(month!=2&&month!=4&&month!=6&&month!=9&&month!=11)
- {
- if(day==32)
- {
- day=0;
- month++;
- if(month==13)
- {
- month=0;
- year++;
- }
- }
- }
- if(month==4||month==6||month==9||month==11)
- {
- {
- day=0;
- month++;
- if(month==13)
- {
- month=0;
- year++;
- }
- }
- }
-
- }
- }
- }
- }
- /*
- *初始化函數(shù),包括LCD1602初始化
- *中斷的開啟,優(yōu)先級(jí)的設(shè)置
- *定時(shí)器的工作方式,計(jì)算初值等。
- */
- void init()
- {
- P0M0=0;
- P0M1=0;
- P2M0=0;
- P2M1=0;
- lcdwait();
- lcdinit();
- ET0 = 1;
- EX0 = 1; //外部中斷0允許
- EX1 = 1; //外部中斷1允許
- PX1 = 0; //調(diào)整外部中斷1的優(yōu)先級(jí)
- PT0 = 1; //調(diào)整定時(shí)器0中斷優(yōu)先級(jí)
- IT1 = 1;
- TMOD = 0x01; //time0為定時(shí)器,方式1
- TH0 = 0x3C;//(65535 - 50000) / 256; //預(yù)置計(jì)算初值
- TL0 = 0xB0;//(65535 - 50000) % 256;
- IT0 = 1; //低電平有效
- TR0 = 1; //為1時(shí)啟動(dòng)計(jì)數(shù)
- EA = 1;
- }
- /*
- *字符分離函數(shù)
- *將兩位的字符分離出十位和個(gè)位
- */
- void write_liangwei(uchar add,uchar date)
- {
- uchar shi,ge;
- shi=date/10;//分解一個(gè)2位數(shù)的十位和個(gè)位
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
51單片機(jī)實(shí)驗(yàn)_在1602上制作電子鐘(包含日期).rar
(227.01 KB, 下載次數(shù): 84)
2019-6-2 00:11 上傳
點(diǎn)擊文件名下載附件
使用STC51單片機(jī)在1602上制作的電子鐘
具體的思路和過(guò)程在壓縮包里。 壓縮包包含工程文件和實(shí)驗(yàn)報(bào)告。
|