是时序上出问题了,写入操作没有完成时序? |
Diameter 发表于 2023-10-27 16:56 你画个框图就知道逻辑错在哪里了 ![]() |
我之前试过修改不成功,后来每次修改之后重新初始化DS1302就可以了。 |
man1234567 发表于 2023-10-27 14:59 逆天我跟着视频教程做的 DS1302写完还要加保存程序么 不是写入 就自动覆盖DS1302芯片原来的数据啊 |
Diameter 发表于 2023-10-27 11:55 细读我的注释就知道了。 改的方式很多,比如模式的切换可以在相应模式工作完成后进行。 你的程序现在是显示模式时写时间到1302而修改后不保存只是重读1302再显示。 |
man1234567 发表于 2023-10-26 18:18 “switch(MODE)//选择显时(模式0)和调时(模式1),顺序执行不受按键影响: { case 0:TimeShow();break;//显时(因为在按下键后已反转模式,因此显示的以是重新读1302的时间而不是调整后的时间,此时显示的时间不是以前的而是以前的时间加上你在调时中停留的时间,理论有一定概率显示是和以前一样的)” 为啥我的DS1302_SetTime只要调用过不就会把我全局数组里改变的时间写到DS1302里面 我DS1302不应该存在以前的时间的啊 |
本帖最后由 man1234567 于 2023-10-27 09:59 编辑 主要看主程序里的注释自己调整就好,总体感觉有些啰嗦有点乱 ![]() #include <REGX51.H> #include "LCD1602.h" #include "DS1302.h" #include "Timer0.h" #include "Key.h" unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag; void TimeShow(void)//读时间并按指定位置显示 { DS1302_ReadTime();//读时间 LCD_ShowNum(1,1,DS1302_Time[0],2);//按指定位置显示年 LCD_ShowNum(1,4,DS1302_Time[1],2);//按指定位置显示月 LCD_ShowNum(1,7,DS1302_Time[2],2);//按指定位置显示日 LCD_ShowNum(2,1,DS1302_Time[3],2);//按指定位置显示时 LCD_ShowNum(2,4,DS1302_Time[4],2);//按指定位置显示分 LCD_ShowNum(2,7,DS1302_Time[5],2);//按指定位置显示秒 } void TimeSet(void)//修改时间并实时显示 { if(KeyNum==2)//按下2号键 { TimeSetSelect++;//年月日时分秒循环跳转 if(TimeSetSelect>5)//单向跳转的防溢出 { TimeSetSelect=0; } } if(KeyNum==3)//按下3号键 { DS1302_Time[TimeSetSelect]++;//时间内容循环跳转,上行,+ if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年 if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月 if(DS1302_Time[1]==1||DS1302_Time[1]==3||DS1302_Time[1]==5||DS1302_Time[1]==7||DS1302_Time[1]==8||DS1302_Time[1]==10||DS1302_Time[1]==12)//适应月大小等 { if(DS1302_Time[2]>31)//双月大防溢出 { DS1302_Time[2]=1; } } else if(DS1302_Time[1]==4||DS1302_Time[1]==6||DS1302_Time[1]==9||DS1302_Time[1]==11)//单月小防溢出 { if(DS1302_Time[2]>30) { DS1302_Time[2]=1; } } else if(DS1302_Time[1]==2)//2月平润防溢出 { if(DS1302_Time[0]%4==0) { if(DS1302_Time[2]>29){DS1302_Time[2]=1;} } else { if(DS1302_Time[2]>28){DS1302_Time[2]=1;} } } if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时防溢出 if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分防溢出 if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒防溢出 // DS1302_SetTime();//不奇怪,原因看看主程序注释。 } if(KeyNum==4)////时间内容循环跳转,下行,- { DS1302_Time[TimeSetSelect]--; if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//同+相关原理,有些啰嗦可以合写 if(DS1302_Time[1]<1){DS1302_Time[1]=12;} if(DS1302_Time[1]==1||DS1302_Time[1]==3||DS1302_Time[1]==5||DS1302_Time[1]==7||DS1302_Time[1]==8||DS1302_Time[1]==10||DS1302_Time[1]==12) { if(DS1302_Time[2]<1) { DS1302_Time[2]=31; } if(DS1302_Time[2]>31) { DS1302_Time[2]=1; } } else if(DS1302_Time[1]==4||DS1302_Time[1]==6||DS1302_Time[1]==9||DS1302_Time[1]==11) { if(DS1302_Time[2]<1) { DS1302_Time[2]=30; } if(DS1302_Time[2]>30) { DS1302_Time[2]=1; } } else if(DS1302_Time[1]==2) { if(DS1302_Time[0]%4==0) { if(DS1302_Time[2]<1){DS1302_Time[2]=29;} if(DS1302_Time[2]>29){DS1302_Time[2]=1;} } else { if(DS1302_Time[2]<1){DS1302_Time[2]=28;} if(DS1302_Time[2]>28){DS1302_Time[2]=1;} } DS1302_SetTime(); } if(DS1302_Time[3]<0){DS1302_Time[3]=23;} if(DS1302_Time[4]<0){DS1302_Time[4]=59;} if(DS1302_Time[5]<0){DS1302_Time[5]=59;} } if(TimeSetSelect==0&&TimeSetFlashFlag==1){LCD_ShowString(1,1," ");}//依选择调整类别的显示定位,同样感觉啰嗦 else{ LCD_ShowNum(1,1,DS1302_Time[0],2);} if(TimeSetSelect==1&&TimeSetFlashFlag==1){LCD_ShowString(1,4," ");} else{ LCD_ShowNum(1,4,DS1302_Time[1],2);} if(TimeSetSelect==2&&TimeSetFlashFlag==1){LCD_ShowString(1,7," ");} else{ LCD_ShowNum(1,7,DS1302_Time[2],2);} if(TimeSetSelect==3&&TimeSetFlashFlag==1){LCD_ShowString(2,1," ");} else{ LCD_ShowNum(2,1,DS1302_Time[3],2);} if(TimeSetSelect==4&&TimeSetFlashFlag==1){LCD_ShowString(2,4," ");} else{ LCD_ShowNum(2,4,DS1302_Time[4],2);} if(TimeSetSelect==5&&TimeSetFlashFlag==1){LCD_ShowString(2,7," ");} else{ LCD_ShowNum(2,7,DS1302_Time[5],2);} // DS1302_SetTime();//写时间,可以退出调整后写,否则过于频繁 } void main() { LCD_Init();//1602初始化,图片中正常显示就没看了 DS1302_Init();//1302初始化,图片中正常显示就没看了 Timer0_Init();//定时器初始化,建议在调整时间开始时执行,停留在调时状态过长时自动返回显示 LCD_ShowString(1,1," - - ");//美化上行 LCD_ShowString(2,1," : : ");//美化下行 while(1)//主循环,先读按键,有1按下时反转状态关并执行相关语句,然后有无按1键都选择状态执行显示/写时。 { KeyNum=Key();//读按键,1为调时/显时切换,2为调时时选择调整类别,3、4分别是调整的+和-。 if(KeyNum==1)//按下1号键后切换调时/显示 { if(MODE==0)//如果正常显示时 { MODE=1;//立即先切换到调时模式 TimeSetSelect=0;//然后选择从年开始调整,然后并不立即调时,而是随后写入时间 } else if(MODE==1)//如果调时模式时 { MODE=0;//立即先切换到正常显示模式,然后执行调时 DS1302_SetTime();//开始调时,随后不执行写时(TimeSet();),往下执行就是显示新读取1302的时间 } } switch(MODE)//选择显时(模式0)和调时(模式1),顺序执行不受按键影响: { case 0:TimeShow();break;//显时(因为在按下键后已反转模式,因此显示的以是重新读1302的时间而不是调整后的时间,此时显示的时间不是以前的而是以前的时间加上你在调时中停留的时间,理论有一定概率显示是和以前一样的) case 1:TimeSet();break;//写时间(因为在按下键后已反转模式所以不在调时后执行,此时并写入时间上次读出的时间,不按键就一直这样写且理论上极小概率可能回退一秒,再按1键就进入调时再反转进入显示模式) } } } void Timer0_Routine() interrupt 1//每隔一秒执行一次中断 { static unsigned int T0Count; TH0=64535/256; TL0=64535%256; T0Count++; if(T0Count>=500) { T0Count=0; TimeSetFlashFlag=!TimeSetFlashFlag; } } |
把单片机STC89C56换成89C52,单片机性能不完全一致 |
Diameter 发表于 2023-10-25 21:23 把这个示例的端口定义按你的实际电路重新定义即可运行。 ![]() ![]() |
那就改为修改立即生效,不能成功的原因极大可能是读取,或在调节时停止读取并在更新后恢复读取. |
没有细看你的代码图片,能读写,说明时序正常,显示不对可能是你的数据转换没做好: 1302读写的是十进制BCD码,你该不会是当做16进制来处理了吧? |
全部的源代码和开发板原理图已上传 |