|
單片機(jī)復(fù)位后會(huì)先檢測(cè)年份是否是2017年,不是就會(huì)復(fù)位1302,是2017年就不初始化1302。采用8位數(shù)碼管來(lái)顯示時(shí)間,日歷,用的是ds1302時(shí)鐘芯片,
S2是設(shè)置鍵,在任何時(shí)候按下超過(guò)2MS都可以進(jìn)入設(shè)置函數(shù)。
S3在正常走時(shí)時(shí)按下,會(huì)顯示日期,日期格式是2017.10.03;松開(kāi)S3后日期會(huì)延時(shí)顯示約6秒。
在設(shè)置功能里面,S3是數(shù)字減,S4是數(shù)字加。設(shè)置功能會(huì)在沒(méi)有按下按鍵后開(kāi)始延時(shí),延時(shí)約6秒
即可退出設(shè)置。
S2設(shè)置的順序是秒,分,時(shí),日,月,年,退出,秒,分,。。。。循環(huán),未按按鍵會(huì)自動(dòng)退回到主界面
上機(jī)測(cè)試請(qǐng)用杜邦線將時(shí)鐘模塊的TSCLK,TIO,TRST,分別對(duì)應(yīng)連接到P33,P34,P35,
連接方式不能與按鍵,串行通訊口,顯示用的數(shù)據(jù)口相沖突,可自己在程序上方sbit的位置進(jìn)行修改。
軟件大都加了注解,不明白可以多交流。
本程序上只要稍加一點(diǎn)改動(dòng)即可加入鬧鐘,有興趣的朋友可以自己修改。
單片機(jī)源程序如下:
- //顯示格式24-35-25 ,小時(shí)-分鐘-秒鐘, 按下S3后,顯示年月日,2017.09.10,延時(shí)6秒后返回
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define sce timedate[1]
- #define min timedate[2]
- #define hour timedate[3]
- #define date timedate[4]
- #define week timedate[6]
- #define month timedate[5]
- #define year timedate[7]
- uchar displaychar1[8]={0,1,2,3,4,5,6,7},a,ya,ja ; //a結(jié)尾的字符都用來(lái)專(zhuān)門(mén)延時(shí),a通用,ya日期延時(shí)程序用
- uchar commandchar[9]={0,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e}; //與timedate對(duì)應(yīng),分別控制每個(gè)寄存器的寫(xiě),讀時(shí)數(shù)組+1,第8個(gè)數(shù)是控制寫(xiě)保護(hù)位
- uchar timedate[8],sdat,seta,m;
- bit s,s2,s3,s4,K,setbit,sk;
- sbit d = P2^6;
- sbit w = P2^7;
- sbit S2 = P3^0;
- sbit S3 = P3^1;
- sbit S4 = P3^2;
- sbit SCLK = P3^3;
- sbit TIO = P3^4;
- sbit TRST = P3^5;
- uchar LD = 1; //************數(shù)碼管,亮度調(diào)節(jié),0最小,10最高,越亮越閃 因會(huì)影響開(kāi)始信號(hào)查詢(xún)時(shí)間,建議最高設(shè)置為3**************
- unsigned char code duan[]=
- { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00 }; //段選碼0-9
- void timeout(uchar a)
- {
- uchar b;
- for(;a>0;a--)
- for(b=114;b>0;b--);
- }
- void timeout5us()
- {
- _nop_();
- }
- void display() //兩個(gè)數(shù),分別記錄鍵值和重復(fù)碼個(gè)數(shù)
- {
-
- P0 = 0xfe; w = 1; w = 0; //顯示1位
- P0 = (displaychar1[0]); d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
-
- P0 = 0xfd; w = 1; w = 0; //顯示2位
- P0 = displaychar1[1]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
- P0 = 0xfb; w = 1; w = 0; //顯示3位
- P0 = displaychar1[2]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
- P0 = 0xf7; w = 1; w = 0; //顯示4位
- P0 = displaychar1[3]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選,否則下一個(gè)位選變化后由于段選沒(méi)變會(huì)將此位信息顯示到下一個(gè)位。
-
- P0 = 0xef; w = 1; w = 0; //顯示5位
- P0 = displaychar1[4]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
-
- P0 = 0xdf; w = 1; w = 0; //顯示6位
- P0 = displaychar1[5]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
- P0 = 0xbf; w = 1; w = 0; //顯示7位
- P0 = displaychar1[6]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選
- P0 = 0x7f; w = 1; w = 0; //顯示8位
- P0 = displaychar1[7]; d = 1; d = 0;
- timeout(LD);
- P0 = 0; d = 1; d = 0; //清除段選,否則下一個(gè)位選變化后由于段選沒(méi)變會(huì)將此位信息顯示到下一個(gè)位。
-
- }
- /************************************************************************************
- -------------------------------以下是與時(shí)鐘芯片的數(shù)據(jù)時(shí)序---------------------------*/
- //寫(xiě)控制和一個(gè)字節(jié)
- void sendchar(uchar csdat,uchar sdat)
- { SCLK = 0;
- TRST = 1;
- for(a=0;a<8;a++)
- {
- SCLK = 0;
- TIO = (csdat%2);
- SCLK = 1;
- csdat >>=1;
- }
- for(a=0;a<8;a++)
- {
- SCLK = 0;
- TIO = (sdat%2);
- SCLK = 1;
- sdat >>=1;
- }
- SCLK = 0;
- TRST = 0;
- }
- //讀一個(gè)字節(jié)
- uchar receviechar(uchar crdat)
- {
- uchar rdat;
- TRST = 1;
- // TIO = 1;
- TRST = 1;
- for(a=0;a<8;a++)
- {
- SCLK = 0;
- TIO = (crdat%2);
- SCLK = 1;
- crdat >>=1;
- }
- for(a=0;a<8;a++)
- {
- SCLK = 1;
- rdat >>= 1;
- SCLK = 0;
-
- if(TIO)
- rdat = rdat|0x80;
- }
- SCLK = 0; TRST = 0;
- return rdat ;
- }
- //讀取時(shí)分秒
- void readtime()
- {
- sendchar(0x8e,0);
- hour = receviechar(0x85);
- min = receviechar(0x83);
- sce = receviechar(0x81);
- sendchar(0x8e,0x80); //
-
- }
- //讀取年月日
- void readyear()
- {
- sendchar(0x8e,0);
- date = receviechar(0x87);
- month = receviechar(0x89);
- year = receviechar(0x8d);
- sendchar(0x8e,0x80); //
-
- }
- //=========================鍵盤(pán)掃描,用定時(shí)器延時(shí)================================
- bit jianpan(K)
- {
- if((!K)&TF0) //如果S2按下且計(jì)時(shí)器0溢出
- {
- TF0 = 0;
- ja++;
- if(ja>=2)
- {// P1 = 0;
- TR0 = 0; //每次按下后都會(huì)關(guān)閉定時(shí)器,后面的程度會(huì)檢測(cè)松手,松開(kāi)按鍵后會(huì)重新打開(kāi)定時(shí)器,可以保護(hù)每次按下只起作用一次
- ja = 0;
- s = 1;
- }
- return s;
- }
- return s;
- }
- //===========================================================================================================
- //**********************************************設(shè)置時(shí)間日期子函數(shù)*******************************************
- //===========================================================================================================
- void settime()
- {
- // uchar sdat,seta;
- // bit sk;
- setbit=1; //設(shè)置控制標(biāo)識(shí),進(jìn)本函數(shù)后先就讓標(biāo)識(shí)打開(kāi),在下面延時(shí)跳出前都會(huì)一直跳入設(shè)置功能函數(shù)
- if(TF1&(s2==s3==s4==0)) //沒(méi)有按鍵按下時(shí)用定時(shí)器1來(lái)延時(shí)跳出
- {
- TF1=0;
- seta ++;
- }
- if(!(s2==s3==s4==0)) seta = 0; //延時(shí)時(shí)間超過(guò)一定值,或者有按鍵被按下(注意!這個(gè)符號(hào))時(shí),時(shí)間會(huì)被延長(zhǎng)
- if(s3); //P1++; //P1++無(wú)用:調(diào)試軟件時(shí)檢測(cè)運(yùn)行的次數(shù)
- if(seta>=70)
- {
- setbit=0; //關(guān)閉設(shè)置
- sdat = 0;
- }
- if(sk!=s2) //sk用來(lái)做s2的中間暫存數(shù)據(jù),用來(lái)用來(lái)識(shí)別S2是否變化過(guò)
- {
- sk = s2;
- if(s2)
- sdat ++; //每次進(jìn)行一次S2動(dòng)作時(shí)才自加一次SDTA
- if(sdat ==6)sdat=7; //跳過(guò)星期,本程序不顯示星期
- }
- m = timedate[sdat]/16*10+timedate[sdat]%16; //m用10進(jìn)制存下
- if(s3) m--;
- if(s4) m++;
- switch (sdat) //每次進(jìn)入設(shè)置的對(duì)應(yīng)操作判斷
- {
- case 1:
- if(m>59) m = 0; break;
- case 2:
- if(m>59) m = 0; break;
- case 3:
- if(m>23) m = 0; break;
- case 4:
- if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11) //小月
- {
- if(m>30) m = 1; break;
- }
- if(timedate[5]==2&(timedate[7]%4==0)) //閏年2月
- {
- if(m>29) m=1; P1++; break; //
- }
- if(timedate[5]==2&(timedate[7]%4!=0)) //平年2月
- {
- if(m>28) m=1; break;
- }
- if(m>31) m =1; break; //其它月分情況
- case 5:
- if(m>12) m = 1; break;
- case 6: sdat++; //跳過(guò)星期本程序不顯示星期
- if(m>7) m = 1; break;
- case 7:
- if(m>99) m = 0; break;
- default : /****不在判斷范圍的進(jìn)行初始化處理*/
- sdat = 0; sk=0; setbit = 0;s2 = 0;// P1++; //本程序所有P1++都是測(cè)試軟件運(yùn)行情況用 //每次在不滿(mǎn)足條件時(shí)自動(dòng)讓數(shù)據(jù)初始化,
- break;
- //s2=0是優(yōu)化點(diǎn),在按下S2后按鍵標(biāo)識(shí)不會(huì)清零,松手時(shí)程序已重復(fù)運(yùn)行了很多遍,所以會(huì)重新跳回設(shè)置的第一位,加本命令可以讓設(shè)置判斷失效,不進(jìn)設(shè)置頁(yè)。
- }
- //==================================
- //setbit為1則說(shuō)明以上有成立的條件,需要發(fā)送修改數(shù)據(jù)
- if(setbit)
- {
- sendchar(0x8e,0); //去寫(xiě)保護(hù)
- sendchar(commandchar[sdat],m/10*16+m%10); //將改好的數(shù)字發(fā)送到1302
- sendchar(0x8e,0x80); //加寫(xiě)保護(hù)
-
- if(seta%5>2&seta<50)
- timedate[sdat] = 0xbb; //設(shè)置延時(shí)操作期間控制閃爍時(shí)間
- } //顯示空,對(duì)應(yīng)段選的兩位11;0xbb/16=11,0xbb%16=11 ,而上面段選數(shù)組中第12個(gè)數(shù)是顯示空
- //寫(xiě)程序時(shí)用的測(cè)試語(yǔ)句,無(wú)用時(shí)未刪供復(fù)習(xí)時(shí)看看當(dāng)時(shí)的思路
- /* switch (sdat)
- {
- case 1:
- P1=0xfe;
- m = sce;
- if(s4) m++;
- if(s3) m--;
-
- break;
- case 2:
- P1=0xfd; break;
- case 3:
- P1=0xfb; break;
- case 4
- :P1=0xf7; break;
- case 5:
- P1=0xef; break;
- case 6:
- P1=0xdf; break;
- case 7:
- P1=0xbf; break;
- case 8:
- P1=0x7f; break;
- default :
- sdat = 0;sk=0; //每次在不滿(mǎn)足條件時(shí)自動(dòng)讓數(shù)據(jù)初始化,
- break;
- } */
- }
- //===================================================================================
- //============================== 主函數(shù)==============================================
- main()
- {
-
- SCLK = 0 ;
- TRST = 0 ;
- readyear(); //讀取年月日
- if(year!=0x17) //如果不是2017年,就初始化1302 ,給初值是17年10月03日,12:11:15
- {
- sendchar(0x8e,0);
- sendchar(0x80,0x15);
- sendchar(0x82,0x11);
- sendchar(0x84,0x12);
-
- sendchar(0x86,0x03);
- sendchar(0x88,0x10);
- sendchar(0x8c,0x17);
- sendchar(0x8e,0x80);
- }
- TMOD = 0x12; //設(shè)置定時(shí)器工作模式
- TR1 = 1;
- TR0 = 1;
- while(1)
- {
- if(!S2) s2 = jianpan(S2);
- if(!S3) s3 = jianpan(S3);
- if(!S4) s4 = jianpan(S4);
-
- TRST = 0;
- /*以下是開(kāi)始年月日自動(dòng)歸零的問(wèn)題修改,問(wèn)題產(chǎn)生原因是開(kāi)始沒(méi)有加!setbit這個(gè)條件,程序在運(yùn)行到設(shè)置年月日時(shí)依然會(huì)進(jìn)
- 入下面這個(gè)判斷,然后再進(jìn)入設(shè)置,但是年月日在這里還沒(méi)有讀數(shù),所以這里的設(shè)置就會(huì)進(jìn)入M=0然后加或減,從而讓設(shè)置值
- 出現(xiàn)錯(cuò)誤
- */
- if((!ya&(!setbit)&(!s3))|(setbit&(sdat<4))) //如果S2沒(méi)有被按下且不在顯示年月日的延時(shí)范圍,而且設(shè)置標(biāo)識(shí)為0時(shí),或者在標(biāo)識(shí)為1但是設(shè)置值在123中時(shí),則正常顯示時(shí)間格式
- {
- readtime(); //P1++; //先讀一下時(shí)間然后再判官設(shè)置程序,這樣的主要目的是讓初m的值由1302決定。
- if(s2|setbit) //按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
- {
- ya = 0;
- settime();
- }
- displaychar1[0] = duan[hour/16];
- displaychar1[1] = duan[hour%16];
- displaychar1[2] = duan[10];
- displaychar1[3] = duan[min/16];
- displaychar1[4] = duan[min%16];
- displaychar1[5] = duan[10];
- displaychar1[6] = duan[sce/16];
- displaychar1[7] = duan[sce%16];
- }
- if(((!setbit)&s3)|ya>0|(setbit&sdat>3))
- {
- if(TF1&!setbit)
- {
- ya++; //非設(shè)置頁(yè)面才進(jìn)去日期延時(shí)
- TF1 = 0;
- }
- readyear();
- if(s2|setbit) //按下S2或設(shè)置標(biāo)識(shí)打開(kāi)時(shí)會(huì)進(jìn)入本判斷
- {
- ya = 0; //進(jìn)設(shè)置后會(huì)關(guān)閉日期顯示延時(shí)
- settime();
- }
- displaychar1[0] = duan[2];
- displaychar1[1] = duan[0];
- displaychar1[2] = duan[year/16];
- displaychar1[3] = duan[year%16]|0x80;
- displaychar1[4] = duan[month/16];
- displaychar1[5] = duan[month%16]|0x80;
- displaychar1[6] = duan[date/16];
- displaychar1[7] = duan[date%16];
- if(ya>70) ya =0;
- //日期延時(shí)約6秒,大約時(shí)間,與計(jì)時(shí)器和程序的運(yùn)行有關(guān)。
- } //P1=s; P1=~P1;
- s3 = s4 =0; // P1 = 255;
- if(S2==S3==S4==1)
- { // P1=255;
- ja = 0;
- TR0 = 1;
- s2= s3= s4= 0; //松開(kāi)按鍵后恢復(fù)計(jì)時(shí)器并清零按鍵值
- s = 0; //為了快速跳時(shí),s清零放在了松手檢測(cè)中,s3和s4在按下不放后會(huì)重復(fù)跳值,想要每次按下只起作用一次
- } //的話,請(qǐng)將s放在本循環(huán)外面這個(gè)循環(huán)后面
- for(a=0; a<50;a++) //一個(gè)循環(huán)顯示50次數(shù)碼管
- display();
- }
- }
復(fù)制代碼
所有資料51hei提供下載:
1302顯示可調(diào)時(shí)間日期.rar
(218.59 KB, 下載次數(shù): 181)
2017-11-26 21:01 上傳
點(diǎn)擊文件名下載附件
附件
|
評(píng)分
-
查看全部評(píng)分
|