使用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);
- }
- }
复制代码 |