|
附件里有完整源碼,原理圖,PCB圖,protel格式的,PCB板和12864的尺寸一樣大,采用大字符數(shù)字顯示,效果還是比較好的。源碼是論壇里的,做了些改動;
大數(shù)字顯示時間,冒號閃爍;
加背光調(diào)亮度的代碼,溫度顯示有點跳動,后來就改成背光開關(guān)了。
DS1302的接晶振的腳留有電容的位置,加10~20pF的電容可以微調(diào)時間的精度。有備用電池,掉電時鐘芯片繼續(xù)走時。
實物圖:
615695752773691910.jpg (85.8 KB, 下載次數(shù): 130)
下載附件
2017-6-23 09:16 上傳
電路原理圖:
原理圖.jpg (51.44 KB, 下載次數(shù): 119)
下載附件
2017-6-23 09:16 上傳
背面圖:
912683349858296307.jpg (104.07 KB, 下載次數(shù): 137)
下載附件
2017-6-23 09:16 上傳
pcb圖(protel99格式):
0.png (42 KB, 下載次數(shù): 114)
下載附件
2017-6-23 21:18 上傳
晶振腳接的15P的電容,測試下來,每天慢2秒,請高手看一下,能不能寫一個自動校正誤差的函數(shù),我在數(shù)碼管時鐘的程序里寫過自動校正誤差的函數(shù),但是在這里不行。
以下是數(shù)碼管時鐘自動校正誤差的函數(shù):- /*********************************************************************************
- 描述: 8位共陰數(shù)碼管時鐘,顯示88-88-88樣式,正常走時的時候,兩個“-”0.5秒閃爍一次;
- 調(diào)時:按KEY1按鍵第1次分鐘位閃爍,再按KEY2一次分鐘加1,按KEY3一次分鐘減1,長按連加連減;
- 按KEY1按鍵第2次小時位閃爍,再按KEY2一次小時加1,按KEY3一次小時減1,長按連加連減;
- 按KEY1按鍵第3次,秒從零開始累加,時鐘回到正常走時;
- 對時的時候先調(diào)好時、分,分鐘要比參考時間的分鐘加1分,
- 再看參考時間的秒數(shù)到了59再按KEY1按鍵的第3次,這樣對時可以很準(zhǔn)的。
- 加備用電池,掉電走時
- 仿真 實物都通過. 11.0592MHz晶振,STC89C52RC,兩個74HC573鎖存器做位選、段選
- **********************************************************************************/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit TSCLK = P1^0;//時鐘線 接到P10上用杜邦線
- sbit TIO = P1^1;//數(shù)據(jù)線,接到P11上
- sbit TRST = P1^2;//使能端,接到P12上
- sbit wela = P2^7; //位選
- sbit dula = P2^6; //段選
- sbit KEY1=P3^0; //按鍵 設(shè)置/確認(rèn)
- sbit KEY2=P3^1; //按鍵 加
- sbit KEY3=P3^2; //按鍵 減
- uchar snum,fnum;
- char shi,fen,miao;
- uchar ss;
- char FunctionKeyNum=0; //功能鍵鍵值
- char FuncTempNum=0; //功能鍵臨時鍵值
- typedef enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat}; //鍵值狀態(tài)值
- bit flag=0; //自動校時標(biāo)志位
- /***********寫時分秒地址************/
- #define write_shi 0x84
- #define write_fen 0x82
- #define write_miao 0x80
- #define write_ram 0xc0
- /***********讀時分秒地址************/
- #define read_shi 0x85
- #define read_fen 0x83
- #define read_miao 0x81
- #define read_ram 0xc1
- // 0 1 2 3 4 5 6 7 8 9
- uchar d[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共陰不帶小數(shù)點
- //uchar dd[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; // 共陰帶小數(shù)點
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=120;y>0;y--);
- }
- void t0_init() //定時50ms一個中斷
- {
-
- TMOD |= 0X01;
- TH0 = (65536-46080)/256;
- TL0 = (65536-46080)%256;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void t1_init()
- {
- TMOD |= 0x10;
- TH1 = 0xDC;
- TL1 = 0x00;
- TR1 = 1;
- }
- void temer0() interrupt 1
- {
- TH0=(65536-46080)/256;
- TL0=(65536-46080)%256;
- ss++;
- if(ss==20)
- ss=0;
-
- }
- void display(uchar shi,uchar fen,uchar miao) //顯示函數(shù)
- {
- if(FunctionKeyNum==0)
- {
- snum=30;
- fnum=30;
- }
-
- if(FunctionKeyNum==1)
- {
- fnum++;
- snum=30;
- }
-
- if(FunctionKeyNum==2)
- {
- snum++;
- fnum=30;
- }
-
-
- if(snum>=30)
- {
- if((shi/10)<1) //如果小時十位小于1,
- {
- dula=1; //消影
- P0=0;
- dula=0;
-
-
- wela=1;
- P0=0xfe; //第1位
- wela=0;
- dula = 1;
- P0=0xff; // 小時十位就不顯示
- dula = 0;
- }
-
- else
- {
- dula=1; //消影
- P0=0;
- dula=0;
-
-
- wela=1;
- P0=0xfe; //第1位
- wela=0;
- dula=1;
- P0=d[shi/10];
- dula=0;
- P0=0xff;
- delay(2);
- }
-
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xfd; //第2位
- wela=0;
- dula=1;
- P0=d[shi%10];
- dula=0;
- delay(2);
-
-
- if(snum==60)
- snum=0;
- }
- // if(miao%2==0) //if(miao%2==0) 1秒閃爍1次
- if(ss>=10) // 這里寫為ss>=10,閃爍頻率可調(diào)
- {
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xfb; //第3位
- wela=0;
- dula=1;
- P0=0x40; //第三位數(shù)碼管顯示“— ”
-
- dula=0;
- delay(2);
-
- }
- else
- {
- dula=1;
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xfb; //第3位
- wela=0;
- dula=1;
- P0=0; //第三位數(shù)碼管不顯示
- dula=0;
- delay(2);
- }
-
-
- if(fnum>=30)
- {
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xf7; //第4位
- wela=0;
- dula=1;
- P0=d[fen/10];
- dula=0;
- delay(2);
-
- dula=1;
- P0=0;
- dula=0;
- wela=1;
- P0=0xef; //第5位
- wela=0;
- dula=1;
- P0=d[fen%10];
- dula=0;
- delay(2);
-
-
- if(fnum==60)
- fnum=0;
- }
-
- // if(miao%2==0) //if(miao%2==0) 1秒閃爍1次
- if(ss>=10) //if(ss>=10)閃爍頻率可調(diào)
- {
- dula=1;
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xdf; //第6位
- wela=0;
- dula=1;
- P0=0x40; //第六位數(shù)碼管顯示“— ”
- dula=0;
- delay(2);
- }
- else
- {
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xdf; //第6位
- wela=0;
- dula=1;
- P0=0; //第六位數(shù)碼管不顯示
- dula=0;
- delay(2);
- }
- //--------------------/
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0xbf; //第7位
- wela=0;
- dula=1;
- P0=d[miao/10]; //秒十位
- dula=0;
- delay(2);
- //--------------------/
- dula=1; //消影
- P0=0;
- dula=0;
-
- wela=1;
- P0=0x7f; //第8位
- wela=0;
- dula=1;
- P0=d[miao%10]; //秒個位
- dula=0;
- delay(2);
- }
- //寫DS1302數(shù)據(jù)
- void Write_DS1302_DAT(uchar cmd, uchar dat)
- {
- uchar i;
- TRST = 0; //拉低使能端
- TSCLK = 0;//拉低數(shù)據(jù)總線
- TRST = 1; //拉高使能端,產(chǎn)生上升沿開始寫數(shù)據(jù)
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = cmd & 0x01; //寫1位數(shù)據(jù),從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產(chǎn)生上升沿數(shù)據(jù)被DS1302讀走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = dat & 0x01; //寫1位數(shù)據(jù),從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產(chǎn)生上升沿數(shù)據(jù)被DS1302讀走
- dat >>= 1; //右移一位
- }
- }
- //讀DS1302數(shù)據(jù)
- uchar Read_DS1302_DAT(uchar cmd)
- {
- uchar i, dat;
- TRST = 0; //拉低使能端
- TSCLK = 0; //拉低數(shù)據(jù)總線
- TRST = 1; //拉高使能端,產(chǎn)生上升沿開始寫數(shù)據(jù)
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = cmd & 0x01;//寫1位數(shù)據(jù),從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產(chǎn)生上升沿數(shù)據(jù)被DS1302讀走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次讀1位,讀8次
- {
- TSCLK = 0; //拉低時鐘總線,產(chǎn)生下降沿,DS1302把數(shù)據(jù)放到TIO上
- dat >>= 1; //右移一位
- if(TIO) dat |= 0x80;//讀取數(shù)據(jù),從最低位開始
- TSCLK = 1; //拉高時鐘總線,以備下一次產(chǎn)生下降沿
- }
- return dat; //返回讀出數(shù)據(jù)
- }
- //數(shù)據(jù)轉(zhuǎn)BCD碼
- uchar Dat_Chg_BCD(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 10;
- dat2 = dat % 10;
- dat2 = dat2 + dat1 * 16;
- return dat2;
- }
- //BCD碼轉(zhuǎn)換為數(shù)據(jù)
- uchar BCD_Chg_Dat(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 16;
- dat2 = dat % 16;
- dat2 = dat2 + dat1 * 10;
- return dat2;
- }
- void init_1302() //初始化函數(shù) 設(shè)置時間
- { //加備用電池,掉電走時
- if((Read_DS1302_DAT(0x81)& 0x80) != 0) //讀出秒數(shù)據(jù),再跟80h(0x80)與運算看結(jié)果,結(jié)果是0則不需要初始化1302;是80h就要初始化!
- {
- Write_DS1302_DAT(0x8e, 0);//清除寫保護(hù)
- Write_DS1302_DAT(0x80, Dat_Chg_BCD(58));//58秒(并且進(jìn)行BCD碼轉(zhuǎn)換)
- Write_DS1302_DAT(0x82, Dat_Chg_BCD(10));//10分
- Write_DS1302_DAT(0x84, Dat_Chg_BCD(9));//9時
- Write_DS1302_DAT(0x8e, 0x80);//開寫保護(hù)
- }
- }
- void read_sf()
- {
- miao = BCD_Chg_Dat(Read_DS1302_DAT(0x81));//讀秒寄存器(并且進(jìn)行BCD碼轉(zhuǎn)換)
- fen = BCD_Chg_Dat(Read_DS1302_DAT(0x83));//讀分寄存器
- shi = BCD_Chg_Dat(Read_DS1302_DAT(0x85));//讀時寄存器
- display(shi,fen,miao);
- }
- void zdjs() //自動校時,這方法測試可行,每天減去快出的秒數(shù)
- {
- if((shi==12)&&(fen==0)&&(miao==4)) // 清翔實驗板上的時鐘每天快4秒
- {
- if(flag==0)
- {
- Write_DS1302_DAT(0x8e,0x00); //寫保護(hù)取消
- Write_DS1302_DAT(write_miao,0x00); //寫秒0,這里是假如每天快4秒,每到這個時候就減去4秒
- Write_DS1302_DAT(0x8e,0x80); //啟動寫保護(hù)
- flag=1; //標(biāo)志位置1,不然這里會成一個死循環(huán)
- }
- }
- if((shi==12)&&(fen==1)&&(miao==0))
- flag=0; //標(biāo)志位清零,準(zhǔn)備第二天校時
- }
- void KeyScan(void)
- {
- static uchar KeyStateTemp1 = 0; //按鍵狀態(tài)臨時存儲值1
- static uchar KeyStateTemp2 = 0; //按鍵狀態(tài)臨時存儲值2
- static uchar KeyStateTemp3 = 0; //按鍵狀態(tài)臨時存儲值3
- static uchar KeyTime = 0; //按鍵延時時間
- bit KeyPressTemp1; //按鍵是否按下存儲值1
- bit KeyPressTemp2; //按鍵是否按下存儲值2
- bit KeyPressTemp3; //按鍵是否按下存儲值3
- KeyPressTemp1 = KEY1; //讀取IO口的鍵值
- switch(KeyStateTemp1)
- {
- case StateInit:
- if(!KeyPressTemp1) //KEY1按下
- KeyStateTemp1 = StateAffirm; //按鍵狀態(tài)切換到確認(rèn)態(tài)
- break;
- case StateAffirm: //確認(rèn)狀態(tài)
- if(!KeyPressTemp1) //按鍵還在按下
- {
- KeyTime = 0;
- KeyStateTemp1 = StateSingle; //按鍵狀態(tài)切換到單擊狀態(tài)
- }
- else KeyStateTemp1 = StateInit; //否則按鍵抬起,回到初始態(tài)
- break;
-
- case StateSingle: //單擊
- if(KeyPressTemp1)
- {
- KeyStateTemp1 = StateInit; //按鍵釋放
- FuncTempNum++; //鍵值加1
- if(FuncTempNum>3) FuncTempNum = 0;
- }
- else if(++KeyTime>100)
- {
- KeyPressTemp1 = StateRepeat;
- KeyTime = 0;
- }
- break;
-
- case StateRepeat: //連發(fā)
- if(KeyPressTemp1)
- KeyStateTemp1 = StateInit;
- else
- {
- if(++KeyTime > 10)
- {
- KeyTime = 0;
- FuncTempNum++;
- if(FuncTempNum>3) FuncTempNum = 0;
- }
- break;
- }
- break;
-
- default :KeyStateTemp1 = KeyStateTemp1 = StateInit; break;
-
- }
- if(FuncTempNum) //只有功能鍵被按下后,增加和減小鍵才有效
- {
- KeyPressTemp2 = KEY2; //讀取I/O口的鍵值
- switch(KeyStateTemp2)
- {
- case StateInit: //按鍵初始狀態(tài)
- if(!KeyPressTemp2) //當(dāng)按鍵按下,狀態(tài)切換到確認(rèn)態(tài)
- KeyStateTemp2 = StateAffirm;
- break;
- case StateAffirm: //按鍵確認(rèn)態(tài)
- if(!KeyPressTemp2)
- {
- KeyTime = 0;
- KeyStateTemp2 = StateSingle;//切換到單次觸發(fā)態(tài)
- }
- else KeyStateTemp2 = StateInit; //按鍵已抬起,切換到初始態(tài)
- break;
- case StateSingle: //按鍵單發(fā)態(tài)
- if(KeyPressTemp2) //按下時間小于1s
- {
- KeyStateTemp2 = StateInit; //按鍵釋放,則回到初始態(tài)
- if(FunctionKeyNum == 1) //若功能鍵第一次按下
- {
- fen++;
- fen=fen/10*16+fen%10; //轉(zhuǎn)為16進(jìn)制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- // write_1302(write_fen,fen); //寫入1302
- read_sf(); //讀出時間,然后顯示
- }
- if(FunctionKeyNum == 2) //若功能鍵第二次按下
- {
- shi++;
- shi=shi/10*16+shi%10; //轉(zhuǎn)為16進(jìn)制
- if(shi==0x24)
- shi=0x00;
- Write_DS1302_DAT(write_shi,shi);
- // write_1302(write_shi,shi);
- read_sf();
- }
- }
- else if(++KeyTime > 100) //按下時間大于1s(100*10ms)
- {
- KeyStateTemp2 = StateRepeat;//狀態(tài)切換到連發(fā)態(tài)
- KeyTime = 0;
- }
- break;
- case StateRepeat: //按鍵連發(fā)態(tài)
- if(KeyPressTemp2)
- KeyStateTemp2 = StateInit; //按鍵釋放,則進(jìn)初始態(tài)
- else //按鍵未釋放
- {
- if(++KeyTime > 10) //按鍵計時值大于100ms(10*10ms)
- {
- KeyTime = 0;
- if(FunctionKeyNum == 1) //若功能鍵第一次按下
- {
- fen++;
- fen=fen/10*16+fen%10; //轉(zhuǎn)為16進(jìn)制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- // write_1302(write_fen,fen); //寫入1302
- read_sf(); //讀出時間,然后顯示
- }
-
- if(FunctionKeyNum == 2) //若功能鍵第二次按下
- {
- shi++;
- shi=shi/10*16+shi%10; //轉(zhuǎn)為16進(jìn)制
- if(shi==0x24)
- shi=0x00;
-
- Write_DS1302_DAT(write_shi,shi);
- // write_1302(write_shi,shi);
- read_sf();
- }
- }
- break;
- }
- break;
- default: KeyStateTemp2 = KeyStateTemp2 = StateInit; break;
- }
- KeyPressTemp3 = KEY3; //讀取I/O口的鍵值
- switch(KeyStateTemp3)
- {
- case StateInit: //按鍵初始狀態(tài)
- if(!KeyPressTemp3) //當(dāng)按鍵按下,狀態(tài)切換到確認(rèn)態(tài)
- KeyStateTemp3 = StateAffirm;
- break;
- case StateAffirm: //按鍵確認(rèn)態(tài)
- if(!KeyPressTemp3)
- {
- KeyTime = 0;
- KeyStateTemp3 = StateSingle; //切換到單次觸發(fā)態(tài)
- }
- else KeyStateTemp3 = StateInit; //按鍵已抬起,切換到初始態(tài)
- break;
- case StateSingle: //按鍵單發(fā)態(tài)
- if(KeyPressTemp3) //按下時間小于1s
- {
- KeyStateTemp3 = StateInit; //按鍵釋放,則回到初始態(tài)
- if(FunctionKeyNum == 1) //若功能鍵第一次按下
- {
- fen--;
- fen=fen/10*16+fen%10; //轉(zhuǎn)為16進(jìn)制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- // write_1302(write_fen,fen);
- read_sf();
- }
- if(FunctionKeyNum == 2) //若功能鍵第二次按下
- {
- shi--;
- shi=shi/10*16+shi%10; //轉(zhuǎn)為16進(jìn)制
- if(shi==-1)
- shi=0x23;
-
- Write_DS1302_DAT(write_shi,shi);
- // write_1302(write_shi,shi);
- read_sf();
- }
- }
- else if(++KeyTime > 100) //按下時間大于1s(100*10ms)
- {
- KeyStateTemp3 = StateRepeat; //狀態(tài)切換到連發(fā)態(tài)
- KeyTime = 0;
- }
- break;
- case StateRepeat: //按鍵連發(fā)態(tài)
- if(KeyPressTemp3)
- KeyStateTemp3 = StateInit; //按鍵釋放,則進(jìn)初始態(tài)
- else //按鍵未釋放
- {
- if(++KeyTime > 10) //按鍵計時值大于100ms(10*10ms)
- {
- KeyTime = 0;
- if(FunctionKeyNum == 1) //若功能鍵第一次按下
- {
- fen--;
- fen=fen/10*16+fen%10; //轉(zhuǎn)為16進(jìn)制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- // write_1302(write_fen,fen);
- read_sf();
- }
- if(FunctionKeyNum == 2) //若功能鍵第二次按下
- {
- shi--;
- shi=shi/10*16+shi%10; //轉(zhuǎn)為16進(jìn)制
- if(shi==-1)
- shi=0x23;
- Write_DS1302_DAT(write_shi,shi);
- // write_1302(write_shi,shi);
- read_sf();
- }
- }
- break;
- }
- break;
- default: KeyStateTemp3 = KeyStateTemp3 = StateInit; break;
- }
- }
- }
- void ExecuteKeyNum()
- {
- if(TF1)
- {
- TF1 = 0;
- TH1 = 0xDC;
- TL1 = 0x00;
- KeyScan();
- }
- switch (FuncTempNum)
- {
- case 1: FunctionKeyNum = 1;
- Write_DS1302_DAT(0x8e,0x00); //寫保護(hù)取消
- Write_DS1302_DAT(write_miao,0x80); // 寫秒80,時鐘停止走時;
- break;
-
- case 2: FunctionKeyNum = 2;
- break;
-
- case 3:
- FunctionKeyNum = 0;
- Write_DS1302_DAT(write_miao,0x00);
- Write_DS1302_DAT(0x8e,0x80); //保護(hù)啟動
- FuncTempNum =0;
- break;
- }
- }
- void main()
- {
- t0_init();
- t1_init();
- init_1302();
- while(1)
- {
- read_sf();
- ExecuteKeyNum();
- zdjs();//自動校時
- }
- }
復(fù)制代碼
單片機源程序:
- /*---------------------------------------------------------------------------
- 單 片 機:STC90C516RD+ (HEX文件不到8K,用STC89C52也可以)
- 晶 振:11.0592MHz
- 時鐘芯片:DS1302
- 測溫芯片:DS18B20
- 接 收 頭:HS0038BD
- 液 晶 屏:LCM-12864-ST7920
- 功能描述: 大數(shù)字顯示時間;能顯示農(nóng)歷、溫度和設(shè)置鬧鈴;有整點報時功能
- 紅外遙控和按鍵都能設(shè)置時間、鬧鈴和背光的開關(guān)
- 實物測試通過
- ------------------------------------------------------------------------------*/
- /*-------------------------------頭文件---------------------------------------*/
- #include <reg52.h>
- #include <intrins.h>
- #include "LCD12864.h"
- #include "DS1302.h"
- #include "DS18B20.h"
- #include "nongli.h"
- #include "displaytime.h"
- #include "zk.h"
- #include "bell.h"
- #include "HW.H"
- #include "delay.h"
- #define uint unsigned int
- #define uchar unsigned char
- /*--------------------定義按鍵-----------------------------------------------*/
- sbit K1 = P3^0; //K1-設(shè)置
- sbit K2 = P3^1; //K2-確認(rèn)、返回
- sbit K3 = P3^3; //K3-加
- sbit K4 = P3^4; //K4-減
- sbit K6 = P3^6; //背光開關(guān)
- sbit BL = P2^7; //背光控制端
- /*---------------------函數(shù)聲明------------------------------*/
- void ds_w0(void);
- void ds_w(void);
- void Conver_week(bit c,uchar year,uchar month,uchar day);
- /*-----------------------------定義全局變量------------------------------*/
- bit w=0; //調(diào)時標(biāo)志位
- unsigned char yy,mo,dd,xq,hh,mm,ss,month_moon,day_moon,week,tiangan,dizhi,moontemp1,moontemp2;//定義時間映射全局變量(專用寄存器)
- signed char address,item,item0,max,mini;
- unsigned char clk_ala[2]={0x00,0x00};//鬧鐘數(shù)據(jù)存放初,始值為00:00
- unsigned char hour,minute,time;//用于鬧鈴的設(shè)置
- //unsigned char ba=5,bi=0;
- /*-----------------------------日期、時間設(shè)置函數(shù)-----------------------------*/
- void tiaozheng(void){
- yy = read_clock(0x8d);//調(diào)用1302時鐘數(shù)據(jù)中的年數(shù)據(jù),從地址0x8d中
- mo = read_clock(0x89);//調(diào)用1302時鐘數(shù)據(jù)中的月數(shù)據(jù),從地址0x89中
- dd = read_clock(0x87);//從1302芯片中讀取日數(shù)據(jù),從地址0x87中
- week = read_clock(0x8b);//從1302芯片中讀取星期數(shù)據(jù),從地址0x8b中
- //----------------------------------
- lcm_w_test(0,0x80);
- lcm_w_word("20");//顯示內(nèi)容字符20
- lcm_w_test(1,(yy/16)+0x30);//函數(shù)參數(shù)1,代表本行寫數(shù)據(jù),YY/16+0X30得出年十位數(shù)字的顯示碼地址,送顯示
- lcm_w_test(1,yy%16+0x30);//函數(shù)
- lcm_w_word("年");
- //----------------------------------
- lcm_w_test(1,(mo/16)+0x30);
- lcm_w_test(1,mo%16+0x30);//與16取余數(shù),得到月份的個位數(shù),加0x30得到該數(shù)字的液晶內(nèi)定顯示碼送顯示
- lcm_w_word("月");//調(diào)用字符顯示函數(shù),顯示文字 月
- //----------------------------------
- /*
- lcm_w_test(0,0x88);//第一個參數(shù)0,表示本行寫入LCM的是指令,指定顯示位置88H(第三行左端)
- lcm_w_word("星期");//調(diào)用字符顯示函數(shù),顯示文字 星期
- lcm_w_test(1,mo%16+0x30);//與16取余數(shù),得到月份的個位數(shù),加0x30得到該數(shù)字的液晶內(nèi)定顯示碼送顯示
- */
- //----------------------------------
- lcm_w_test(1,(dd/16)+0x30);
- lcm_w_test(1,dd%16+0x30);//第一個1參數(shù),表示本行寫數(shù)據(jù),日數(shù)據(jù)與16取余得個位數(shù),加0x30得到顯示碼
- lcm_w_word("日");//顯示字符 日
- //----------------------------------
- if(read_clock(0x85) != hh){//如果程序中的小時與1302芯片中的不同,
- hh = read_clock(0x85);//刷新程序中的小時數(shù)據(jù)
- }
- lcm_w_test(0,0x91);//第一個參數(shù)0,表示本行寫入LCM的是指令,指定顯示位置88H(第三行左端)
- lcm_w_test(1,(hh/16)+0x30);//顯示十位
- lcm_w_test(1,hh%16+0x30);//顯示個位
- lcm_w_word("時");
- //----------------------------------
- if(read_clock(0x83) != mm){//如果1302芯片中的分鐘數(shù)據(jù)與程序中的分鐘變量不相等
- mm = read_clock(0x83);//刷新程序中的分鐘數(shù)據(jù)
- }
- lcm_w_test(1,(mm/16)+0x30);//向液晶寫數(shù)據(jù),顯示分鐘的十位數(shù)
- lcm_w_test(1,mm%16+0x30);//向液晶寫數(shù)據(jù),顯示分鐘的個位數(shù)
- lcm_w_word("分");
- //----------------------------------
- if(read_clock(0x81) != ss){//如果1302芯片中的分鐘數(shù)據(jù)與程序中的秒鐘變量不相等(0x81為讀秒數(shù)據(jù)0x80為寫秒數(shù)據(jù))
- ss = read_clock(0x81);//刷新程序中的秒鐘數(shù)據(jù)
- }
- lcm_w_test(1,(ss/16)+0x30);//向液晶寫數(shù)據(jù),顯示分鐘的十位數(shù)
- lcm_w_test(1,ss%16+0x30);//向液晶寫數(shù)據(jù),顯示分鐘的個位數(shù)
- lcm_w_word("秒");
- //////////////////////////////////////////////////////////////////////
- //=========顯示鬧鐘的設(shè)置時間===================
-
- hour=clk_ala[0]; //取出上一次的鬧鐘小時值
- minute=clk_ala[1]; //取出上一次的鬧鐘分鐘值
-
- lcm_w_test(0,0x88);
- lcm_w_word("鬧鐘---");
- //----------------------------
- lcm_w_test(1,(hour/10)+0x30);//顯示小時十位
- lcm_w_test(1,(hour%10)+0x30);//顯示小時個位
- //----------------------------
- lcm_w_word(":");
- //----------------------------
- lcm_w_test(1,(minute/10)+0x30);//顯示分鐘的十位
- lcm_w_test(1,(minute%10)+0x30);//顯示分鐘的個位
- //----------------------------
- lcm_w_word("----");
- /////////////////////////////////////////////////////////////////////////
- }
- /*****************************************************************************/
- //被調(diào)數(shù)據(jù)加一或減一,并檢查數(shù)據(jù)范圍,寫入1302指定地址保存
- void ds_w(void)
- {
- item0=time;
- item=((read_clock(address+1))/16)*10 + (read_clock(address+1))%16;//時間的調(diào)整
- if(K3 == 0||key_add==1){//如果按動上調(diào)鍵
- item++;//數(shù)加 1
- }
- if(K4 == 0||key_minish==1){//如果按動下調(diào)鍵
- item--;//數(shù)減 1
- }
- if(item>max) item=mini;//查看數(shù)值是否在有效范圍之內(nèi)
- if(item<mini) item=max;//如果數(shù)值小于最小值,則自動等于最大值
- write_clock(0x8e,0x00);//允許寫1302芯片操作
- write_clock(address,(item/10)*16+item%10);//轉(zhuǎn)換成16進(jìn)制寫入1302
- write_clock(0x8e,0x80);//寫保護(hù),禁止寫操作
- }
- /********************************************************************/
- //===============鬧鐘時間的加減設(shè)置======================
- void ds_w0(void)
- {
- item0=time;
- if(K3 == 0||key_add==1){//如果按動上調(diào)鍵
- item0++;//數(shù)加 1
- }
- if(K4 == 0||key_minish==1){//如果按動下調(diào)鍵
- item0--;//數(shù)減 1
- }
- if(item0>max) item0=mini;//查看數(shù)值是否在有效范圍之內(nèi)
- if(item0<mini)item0=max;//如果數(shù)值小于最小值,則自動等于最大值
- time=item0;//調(diào)整后的時間重新賦值給time(time為hour或minute),這步很重要,沒有將無法更新鬧鐘數(shù)據(jù)
- }
- /**********************************************************************************************************/
- //調(diào)整時間子函數(shù),設(shè)置鍵、數(shù)據(jù)范圍、上調(diào)加一,下調(diào)減一功能。
- void Set_time(unsigned char sel){ //根據(jù)選擇調(diào)整的相應(yīng)項目加1并寫入DS1302,函數(shù)參數(shù)是按動設(shè)置鍵的次數(shù)
- write_com(0x30); write_com(0x06);
- lcm_w_test(0,0x98);//第一參數(shù)0表示本行寫入指令,指定下面行的 調(diào)整 顯示起始位置為9AH
- lcm_w_word(">>調(diào)整>> <<<<");//調(diào)用字符顯示函數(shù),顯示 調(diào)整字樣
- /* if(sel==8) {lcm_w_word("星期");address=0x8a; max=7;mini=1;
- tiaozheng();
- ds_w();
- tiaozheng();
- }
- */
- //================================================================
- lcm_w_test(0,0x9c);
- if(sel==7) {lcm_w_word("鬧鐘分"); time=minute;max=59;mini=0;
- tiaozheng();//顯示調(diào)整前的內(nèi)容
- ds_w0();//設(shè)置鬧鐘
- clk_ala[1]=time;//把更新后的分鐘數(shù)據(jù)重新保存
- tiaozheng();//顯示調(diào)整后的內(nèi)容
- }//按動8次顯示 調(diào)整鬧鐘的分鐘部分
- if(sel==6) {lcm_w_word("鬧鐘時");time=hour; max=23;mini=0;
- tiaozheng();
- ds_w0();
- clk_ala[0]=time;//把更新后的小時數(shù)據(jù)重新保存
- tiaozheng();
- }//按動7次顯示 調(diào)整鬧鐘的小時部分
- //================================================================
- if(sel==5) {lcm_w_word("秒鐘");address=0x80; max=59;mini=0;
- tiaozheng(); //調(diào)用日期、時間調(diào)整函數(shù)
- ds_w(); //被調(diào)數(shù)據(jù)加一或減一函數(shù)
- tiaozheng();
- } //秒6,按動6次顯示 調(diào)整秒鐘
- //并指定秒鐘數(shù)據(jù)寫入1302芯片的寫入地址是0x80,秒鐘數(shù)據(jù)的最大值是59,最小值是0
- if(sel==4) {lcm_w_word("分鐘");address=0x82; max=59;mini=0;
- tiaozheng();
- ds_w();
- tiaozheng();
- } //分鐘5,按動5次顯示 調(diào)整分鐘
- //并指定分鐘數(shù)據(jù)寫入1302芯片的地址是0x82,分鐘數(shù)據(jù)的最大值是59,最小值是0
- if(sel==3) {lcm_w_word("小時");address=0x84; max=23;mini=0;
- tiaozheng();
- ds_w();
- tiaozheng();
- } //小時4,按動4次顯示 調(diào)整小時
- //規(guī)定小時數(shù)據(jù)寫入1302芯片的位置是0x84,小時數(shù)據(jù)最大值23,最小值是0
- if(sel==2) {lcm_w_word("日期");address=0x86;
- mo = read_clock(0x89);//讀月數(shù)據(jù)
- moontemp1=mo/16;
- moontemp2=mo%16;
- mo=moontemp1*10+moontemp2;//轉(zhuǎn)換成10進(jìn)制月份數(shù)據(jù)
- yy = read_clock(0x8d);//讀年數(shù)據(jù)
- moontemp1=yy/16;
- moontemp2=yy%16;
- yy=moontemp1*10+moontemp2;//轉(zhuǎn)換成10進(jìn)制年份數(shù)據(jù)
- if(mo==2&&yy%4!=0){max=28;mini=1;}//平年2月28天
- if(mo==2&&yy%4==0){max=29;mini=1;}//閏年2月29天
- if(mo==1||mo==3||mo==5||mo==7||mo==8||mo==10||mo==12){max=31;mini=1;}//31天的月份
- if(mo==4||mo==6||mo==9||mo==11){max=30;mini=1;}//30天的月份
- tiaozheng();
- ds_w();
- tiaozheng(); //調(diào)用日期、時間調(diào)整函數(shù)
- } //日3,按動3次顯示 調(diào)整日期
- //規(guī)定日期數(shù)據(jù)寫入1302的位置地址是0x86,日期最大值31,最小值是1
- if(sel==1) {lcm_w_word("月份");address=0x88; max=12;mini=1;
- tiaozheng();
- ds_w();
- tiaozheng();
- } //月2,按動2次顯示 調(diào)整月份
- //規(guī)定月份寫入1302的位置地址是0x88,月份最大值12,最小值1
- if(sel==0) {lcm_w_word("年份");address=0x8c; max=99; mini=0;
- tiaozheng();
- ds_w(); //被調(diào)數(shù)據(jù)加一或減一函數(shù)
- tiaozheng(); //調(diào)用日期、時間調(diào)整函數(shù)
- } //年1,按動1次顯示 調(diào)整年份,
- //規(guī)定年份寫入1302的地址是0x8c,年份的最大值99,最小值0
- }
- /*********************************************************************
- **********************************************************************
- ************** 主函數(shù) ****************
- **********************************************************************
- /********************************************************************/
- void main()
- {
- unsigned char e=0,f=0,tmp,i;
- IE = 0x81; //允許總中斷中斷,使能 INT0 外部中斷
- TCON = 0x01; //觸發(fā)方式為脈沖負(fù)邊沿觸發(fā)
- IRIN=1; //IO口初始化
- // TMOD |=0x02;
- //// EA=1;
- // ET0=1;
- // TR0=1;
-
-
- BEEP=1;
- K1=1;K2=1;K3=1;K4=1; K6=1;
-
- BL = 0;
- // duan = 1;
- // P0 = 0;
- // duan = 0;
- Init_1302(); //時鐘芯片初始化
- lcm_init(); //液晶初始化
- welcome0(); //調(diào)用歡迎信息1
- DelayM(2000);//延時
- //welcome();DelayM(1000); //調(diào)用歡迎信息2
- lcm_clr(); //清屏
- Clean_12864_GDRAM(); //清屏
- while(1)
- {
- if (w == 0) //正常走時
- {
- displaydate(); //顯示日期
- displaynl(); //顯示農(nóng)歷
- displaytime(); //顯示時間
- read_temp(); //讀取溫度
- ds1820disp(); //顯示溫度
- displayxq(); //顯示星期
-
- //=================以下是鬧鐘的相關(guān)處理===================
-
- if(ala_flag==1){//鬧鐘標(biāo)志位
- set1616pic(6,1,0,2);} //顯示"鬧鐘圖標(biāo)"
- else{
- set1616pic(6,1,0,3);}//關(guān)閉"鬧鐘圖標(biāo)"顯示
- //----------------------------------------
- tmp=read_clock(0x85);//取出1302小時
- i = tmp/16;
- tmp = tmp&0x0f;
- tmp = tmp + i*10;
- if(clk_ala[0]==tmp)//與鬧鐘設(shè)定的小時值相同
- {
- tmp=read_clock(0x83);//取出1302分鐘
- i = tmp/16;
- tmp = tmp&0x0f;
- tmp = tmp + i*10;
- if(clk_ala[1]==tmp)//與鬧鐘設(shè)定的分鐘值相同
- {
- if(ala_flag==1)//鬧鐘打開
- {
- alarmbeep();//鬧鈴聲響1分鐘后自動關(guān)閉,
- DelayM(200);//控制鬧鐘響的間隔即頻率
- }
- else BEEP=1;//關(guān)閉蜂鳴器
- }
- else BEEP=1;//關(guān)閉蜂鳴器
- }
- //==============鬧鐘處理結(jié)束=======================
- }
- else {} //========否則啟動調(diào)時=========================
- /*---------------按鍵及紅外遙控設(shè)置時間------------------------------*/
- if (K1 == 0||key_manue==1)
- {
-
- DelayM(8); //按鍵消抖
- /*當(dāng)是調(diào)時狀態(tài) 本鍵用于調(diào)整下一項---------------------------------------------------*/
- if((K1 == 0 && w == 1)||(key_manue==1&&w==1)) //
- {
-
- e++;
- if (e >= 8 ) {e = 0;}
- while(! K1 ); //等待鍵松開
- key_manue=0;
- Set_time(e); beep(); //調(diào)整
- }
- /*當(dāng)是正常狀態(tài)時就進(jìn)入調(diào)時狀態(tài)---------------------------------------------------*/
- if((K1 == 0 && w == 0)||(key_manue==1&&w==0)) //
- {
- key_manue=0;
- lcm_clr();
- Clean_12864_GDRAM(); //清屏
- w=1; //進(jìn)入調(diào)時
- Set_time(e);beep();
- }
- while(K1 == 0); //等待鍵松開
- }
- /*當(dāng)在調(diào)時狀態(tài)時就退出調(diào)時---------------------------------------------------*/
- if (K2 == 0||key_ok==1) //
- { beep();
- DelayM(8);
- if((K2 == 0 && w == 1)||(key_ok==1&&w==1))
- {
- w = 0; //退出調(diào)時
- e = 0; //"下一項"計數(shù)器清0
- }
- if((K2 == 0 && w == 0)||(key_ok==1&&w==0))
- {
- lcm_clr(); Clean_12864_GDRAM();
- write_com(0x30); write_com(0x06);
- welcome();
- while(K2 == 0); //按下K2是顯示歡迎信息
- DelayM(500);key_ok=0;//紅外"OK"按鍵按下時顯示0.5秒鐘的歡迎界面2
- }
- lcm_clr(); Clean_12864_GDRAM();
- // ds_write(0x0a,0x20); //調(diào)時完畢,開啟時鐘振蕩器
-
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
0.png (48.81 KB, 下載次數(shù): 137)
下載附件
2017-6-23 21:13 上傳
全部資料下載地址:
萬年歷12864 紅外 按鍵.rar
(866.48 KB, 下載次數(shù): 337)
2017-6-23 09:17 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|