使用DS1302做一個可調時間的萬年歷,現在按鍵設定時間后,無法將時間保存到DS1302中。按鍵功能是:KEY0長按:進入/保存設定,KEY0在設定界面短按,改變選中,KEY1在設定界面短按加1,長按返回實時顯示界面,不保存設定時間。
單片機源程序如下:
- /******************************************************
- 內容:
- 硬件連接:
- _RD與單片機P2.6引腳連接
- _WR與單片機P2.5引腳連接
- _EN與單片機P2.7引腳連接
- 8位并行數據口與單片機P0組I/O口連接
- **************************************************************/
- #include "reg52.h"
- #include "intrins.h"
- #define uint unsigned int
- #define uchar unsigned char
- sbit _RD=P2^6; //LCD1602數據/命令選擇端位定義
- sbit _WR=P2^5; //LCD1602讀/寫選擇端位定義
- sbit _EN=P2^7; //LCD1602使能信號端位定義
- sbit _SCL=P3^6; //DS1302串行時鐘口位定義
- sbit _SDA=P3^4; //DS1302數據輸入/輸出口位定義
- sbit _RST=P3^5; //DS1302復位口
- sbit DQ=P3^7; //DS18B20總線口位定義
- sbit KEY0=P1^0;
- sbit KEY1=P1^1;
- uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
- uchar time0[8]={20,21,5,19,3,20,51,35}; //存放年、月、日、周,時、分、秒初始值
- uchar time1[8]; //存放DS1302讀取的年、月、日、周,時、分、秒值
- uchar time2[8]; //用于存放臨時設定的時間值
- uchar time3[8]; //用于存放顯示的值
- uint temperature=0; //溫度
- uchar flag0=0,flag1=0; //flag0為設定標志,為0時,顯示實時時間,為1時,顯示設定的值,flag1為溫度零下標志,為0表示正,為1表示負
- uchar num=0; //用于顯示實時溫度和設定時間
- //--------------------------------------DS1302驅動------------------------------------------
- uchar read_byte0(uchar addr) //DS1302讀數據
- {
- uchar i,dat;
- _RST=1; //把RST拉高時,SCL必須為低電平
- addr=addr|0x01; //功能未知
- for(i=0;i<8;i++) //寫地址
- {
- _SDA=(bit)(addr&0x01);
- _nop_();
- _SCL=1; //上升沿,寫入地址數據
- _nop_();
- _SCL=0;
- addr>>=1;
- }
- for(i=0;i<8;i++) //讀數據
- {
- dat>>=1;
- if(_SDA==1)
- dat|=0x80;
- _SCL=1;
- _SCL=0;
- }
- _RST=0;
- _SCL=1; //要加上,不然程序會異常
- _SDA=0; //要加上,不然程序會異常
- _SDA=1;
- return dat;
- }
- /****************************************************************************************************
- 函數功能:DS1302寫一個字節
- 入口參數:地址,命令
- 說明:
- 時間:
- ****************************************************************************************************/
- void write_byte0(uchar addr,uchar com) //DS1302寫數據
- {
- uchar i;
- _RST=1; //把RST拉高時,SCL必須為低電平
- addr=addr&0xfe; //最低位置零
- for(i=0;i<8;i++) //寫地址
- {
- _SDA=(bit)(addr&0x01);
- _nop_();
- _SCL=1; //上升沿,寫入地址數據
- _nop_();
- _SCL=0;
- addr>>=1;
- }
- for(i=0;i<8;i++) //讀數據
- {
- _SDA=(bit)(com&0x01);
- _nop_();
- _SCL=1; //上升沿,寫入地址數據
- _nop_();
- _SCL=0;
- com>>=1;
- }
- _RST=0;
- }
- /*******************************************************************************
- 函數功能:十進制轉BCD碼
- 入口參數:
- 說明:
- 時間:
- ****************************************************************************************************/
- uchar Dec_Bcd(uchar dec) //十進制轉BCD碼
- {
- uchar bcd,tmp;
- tmp=dec/10;
- dec=dec%10;
- bcd=dec+tmp*16;
- return bcd;
- }
- /****************************************************************************************************
- 函數功能:BCD碼轉十進制
- 入口參數:
- 說明:
- 時間:
- ****************************************************************************************************/
- uchar Bcd_Dec(uchar bcd)
- {
- uchar dec,tmp;
- tmp=bcd/16;
- bcd=bcd%16;
- dec=bcd+tmp*10;
-
- return dec;
- }
- /****************************************************************************************************
- 函數功能:向DS1302寫入時鐘數據
- 入口參數:地址
- 說明:
- 時間:
- ****************************************************************************************************/
- void DS1302_Write_Time(void)
- {
- write_byte0(0x8e,0x00); //關閉寫保護
- write_byte0(0x80,0x80); //暫停
- write_byte0(0x90,0xa9); //涓流放電
-
- write_byte0(0x8c,Dec_Bcd(time0[1])); //寫入年
- write_byte0(0x88,Dec_Bcd(time0[2])); //寫入月
- write_byte0(0x86,Dec_Bcd(time0[3])); //寫入日
- write_byte0(0x8a,Dec_Bcd(time0[4])); //寫入星期
- write_byte0(0x84,Dec_Bcd(time0[5])); //寫入時
- write_byte0(0x82,Dec_Bcd(time0[6])); //寫入分
- write_byte0(0x80,Dec_Bcd(time0[7])); //寫入秒
- write_byte0(0x8e,0x80); //打開寫保護
- }
- /****************************************************************************************************
- 函數功能:從DS1302讀出時鐘數據
- 入口參數:
- 說明:
- 時間:
- ****************************************************************************************************/
- void DS1302_Read_Time(void)
- {
- uchar i;
- time1[0]=time0[0];
- time1[1]=read_byte0(0x8c); //年
- time1[2]=read_byte0(0x88); //月
- time1[3]=read_byte0(0x86); //日
- time1[4]=read_byte0(0x8a); //星期
- time1[5]=read_byte0(0x84); //時
- time1[6]=read_byte0(0x82); //分
- time1[7]=read_byte0(0x80); //秒
- for(i=1;i<8;i++)
- {
- time1[i]=Bcd_Dec(time1[i]);
- }
- }
- /****************************************************************************************************
- 函數功能:DS1302初始化
- 入口參數:無
- 說明:
- 時間:
- ****************************************************************************************************/
- void DS1302_Init()
- {
- _RST=0;
- _SCL=0;
- write_byte0(0x80,0x00);
- }
- //------------------------------------------液晶驅動略-------------------------------------------------
- /****************************************************************************************************
- 函數功能:按鍵處理函數
- 入口參數:無
- 說明:
- 時間:
- ****************************************************************************************************/
- void Scan()
- {
- uchar i;
- static uint temp0=0,temp1=0;
- static uchar pass0=0,pass1=0;
- if(KEY0==0)
- temp0++;
- if(temp0>2&&temp0<80&&KEY0==1) //設置界面短按切換焦點
- {
- if(num>0&&num<10)
- num++;
- else if(num>=10)
- num=1;
- }
- if(temp0>=80&&pass0==0) //長按進入設定界面或設定界面保存設定數據
- {
- pass0=1;
- switch(num)
- {
- case 0:
- num=1;
- for(i=1;i<8;i++) //將顯示的當前數據送入臨時數據中
- {
- time2[i]=time1[i];
- }
- break;
- case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:
- num=0;
- for(i=1;i<8;i++)
- {
- time0[i]=time2[i];
- }
- DS1302_Write_Time();
- break;
- }
- }
- if(KEY0==1)
- {
- pass0=0;
- temp0=0;
- }
- if(KEY1==0)
- temp1++;
- if(temp1>2&&temp1<80&&KEY1==1) //設定界面點擊焦點加1
- {
- switch(num)
- {
- case 0: //無焦點
-
- break;
- case 1: //年十位加1
- if(time2[1]<90)
- time2[1]=time2[1]+10;
- else
- time2[1]=time2[1]%10;
- break;
- case 2: //設定年個位
- if(time2[1]%10<9)
- time2[1]++;
- else
- time2[1]=time2[1]/10;
- break;
- case 3: //設定月
- if(time2[2]<12)
- time2[2]++;
- else
- time2[2]=1;
- break;
- case 4: //設定日
- if(time2[2]==1||time2[2]==3||time2[2]==5||time2[2]==7||time2[2]==8||time2[2]==10||time2[2]==12) //31天的月份
- {
- if(time2[3]<31)
- time2[3]++;
- else
- time2[3]=1;
- }
- else if(time2[2]==4||time2[2]==6||time2[2]==9||time2[2]==11) //30天的月份
- {
- if(time2[3]<30)
- time2[3]++;
- else
- time2[3]=1;
- }
- else if(time2[2]==2) //2月份平年28天閏年29天
- {
- if((((time2[0]*100+time2[1])%4==0)&&((time2[0]*100+time2[1])%100!=0))||((time2[0]*100+time2[1])%400==0)) //閏年2月有29天
- {
- if(time2[3]<29)
- time2[3]++;
- else
- time2[3]=1;
- }
- else //平年2月有28天
- {
- if(time2[3]<28)
- time2[3]++;
- else
- time2[3]=1;
- }
- }
- break;
- case 5: //設定星期
- if(time2[4]<7)
- time2[4]++;
- else
- time2[4]=1;
- break;
- case 6: //設定時
- if(time2[5]<23)
- time2[5]++;
- else
- time2[5]=0;
- break;
- case 7: //設定分十位
- if(time2[6]<50)
- time2[6]=time2[6]+10;
- else
- time2[6]=time2[6]%10;
- break;
- case 8: //設定分個位
- if(time2[6]%10<9)
- time2[6]++;
- else
- time2[6]=time2[6]/10;
- break;
- case 9: //設定秒十位
- if(time2[7]<50)
- time2[7]=time2[7]+10;
- else
- time2[7]=time2[7]%10;
- break;
- case 10: //設定秒個位
- if(time2[7]%10<9)
- time2[7]++;
- else
- time2[7]=time2[7]/10;
- break;
- }
- }
- if(temp1>=80&&pass1==0)
- {
- pass1=1;
- if(num!=0)
- num=0;
- }
- if(KEY1==1)
- {
- pass1=0;
- temp1=0;
- }
- }
- void display0(uchar row,uchar line,uchar signal) //row為行位參數,line為列為參數
- {
- static uchar a=0;
- if(row==1)
- a=0x80;
- if(row==2)
- a=0xc0;
- a=a+line-1;
- Wcmd(a);
- Wdat(signal);
- }
- void display1()
- {
- uchar year0,year1,year2,year3,month0,month1,day0,day1;
- uchar hours0,hours1,minutes0,minutes1,seconds0,seconds1;
- uchar temperature0,temperature1,temperature2,temperature3;
- uint j;
- uchar i;
- j++;
- Read_Temp();
- DS1302_Read_Time();
- switch(num)
- {
- case 0:
- for(i=1;i<8;i++)
- time3[i]=time1[i];
- break;
- case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:
- for(i=1;i<8;i++)
- time3[i]=time2[i];
- break;
- }
- year0=time0[0]/10;
- year1=time0[0]%10; //分離出年的十位和個位
- year2=time3[1]/10;
- year3=time3[1]%10; //分離出年的十位和個位
- month0=time3[2]/10;
- month1=time3[2]%10; //分離出月的十位和個位
- day0=time3[3]/10;
- day1=time3[3]%10; //分離出日的十位和個位
- hours0=time3[5]/10;
- hours1=time3[5]%10; //分離出時的十位和個位
- minutes0=time3[6]/10;
- minutes1=time3[6]%10; //分離出分的十位和個位
- seconds0=time3[7]/10;
- seconds1=time3[7]%10; //分離出秒的十位和個位
- temperature0=temperature/1000; //分離出溫度百位
- temperature1=temperature%1000/100; //分離出溫度十位
- temperature2=temperature%100/10; //分離出溫度個位
- temperature3=temperature%10; //分離出溫度十分位
- display0(1,1,table[year0]);
- display0(1,2,table[year1]);
- switch(num)
- {
- case 0: //實時顯示
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 1: //設定年十位
- if(j<20) //年十位閃爍
- display0(1,3,table[year2]);
- else if(j>=20&&j<40)
- display0(1,3,0x20);
- else
- j=0;
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 2: //設定年個位
- display0(1,3,table[year2]); //年十位
- if(j<20) //年個位閃爍
- display0(1,4,table[year3]);
- else if(j>=20&&j<40)
- display0(1,4,0x20);
- else
- j=0;
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 3: //設定月
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- if(j<20) //月閃爍
- {
- display0(1,6,table[month0]);
- display0(1,7,table[month1]); //月個位
- }
- else if(j>=20&&j<40)
- {
- display0(1,6,0x20);
- display0(1,7,0x20);
- }
- else
- j=0;
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 4: //設定日
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- if(j<20)
- {
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
- }
- else if(j>=20&&j<40)
- {
- display0(1,9,0x20);
- display0(1,10,0x20);
- }
- else
- j=0;
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 5: //設定星期
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- if(j<20)
- display0(1,12,table[time3[4]]); //星期
- else if(j>=20&&j<40)
- display0(1,12,0x20);
- else
- j=0;
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 6: //設定小時
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- if(j<20)
- {
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- }
- else if(j>=20&&j<40)
- {
- display0(2,1,0x20);
- display0(2,2,0x20);
- }
- else
- j=0;
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 7: //設定分十位
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- if(j<20)
- display0(2,4,table[minutes0]); //分十位
- else if(j>=20&&j<40)
- display0(2,4,0x20);
- else
- j=0;
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 8: //設定分個位
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- if(j<20)
- display0(2,5,table[minutes1]); //分個位
- else if(j>=20&&j<40)
- display0(2,5,0x20);
- else
- j=0;
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 9: //設定秒十位
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- if(j<20)
- display0(2,7,table[seconds0]); //秒十位
- else if(j>=20&&j<40)
- display0(2,7,0x20);
- else
- j=0;
- display0(2,8,table[seconds1]); //秒個位
- break;
- case 10: //設定秒個位
- display0(1,3,table[year2]); //年十位
- display0(1,4,table[year3]); //年個位
- display0(1,5,'-');
- display0(1,6,table[month0]); //月十位
- display0(1,7,table[month1]); //月個位
- display0(1,8,'-');
- display0(1,9,table[day0]); //日十位
- display0(1,10,table[day1]); //日個位
-
- display0(1,12,table[time3[4]]); //星期
-
- display0(2,1,table[hours0]); //時十位
- display0(2,2,table[hours1]); //時個位
- display0(2,3,':');
- display0(2,4,table[minutes0]); //分十位
- display0(2,5,table[minutes1]); //分個位
- display0(2,6,':');
- display0(2,7,table[seconds0]); //秒十位
- if(j<20)
- display0(2,8,table[seconds1]); //秒個位
- else if(j>=20&&j<40)
- display0(2,8,0x20);
- else
- j=0;
- break;
- }
- if(flag1==0)
- {
- if(temperature>=1000)
- {
- display0(2,10,table[temperature0]); //溫度百位
-
- display0(2,11,table[temperature1]); //溫度十位
- display0(2,12,table[temperature2]); //溫度個位
- display0(2,13,'.');
- display0(2,14,table[temperature3]); //溫度十分位
- }
- else if(temperature>=100&&temperature<1000)
- {
- display0(2,11,table[temperature1]); //溫度十位
- display0(2,12,table[temperature2]); //溫度個位
- display0(2,13,'.');
- display0(2,14,table[temperature3]); //溫度十分位
- }
- else
- {
- display0(2,12,table[temperature2]); //溫度個位
- display0(2,13,'.');
- display0(2,14,table[temperature3]); //溫度十分位
- }
- }
- else
- {
- if(temperature>=100)
- {
- display0(2,10,'-'); //溫度百位
- display0(2,11,table[temperature1]); //溫度十位
- display0(2,12,table[temperature2]); //溫度個位
- display0(2,13,'.');
- display0(2,14,table[temperature3]); //溫度十分位
- }
- else
- {
- display0(2,11,'-'); //溫度十位
- display0(2,12,table[temperature2]); //溫度個位
- display0(2,13,'.');
- display0(2,14,table[temperature3]); //溫度十分位
- }
- }
- display0(2,15,0xdf);
- display0(2,16,'C');
- }
- main()
- {
- Lcd_Init();
- DS1302_Init();
- DS1302_Write_Time();
- display0(1,1,0x20);
- while(1)
- {
- Scan();
- display1();
- delayms(5);
- }
- }
復制代碼 |