Problems writing to DS1302
Hello All,
I am having trouble writing values to my DS1302. I am making a clock and would like to be able to adjust the minutes and hours from the clock itself using push buttons. The code which addresses adjusting the minutes is below.
I have code which sends the time to the debug and can see that the minutes value is increasing and decreasing accordingly however once the buttons are releases the time on reverts back to the original time. In short it does not seem that I am able to write this new minutes value to the DS1302.
If anyone can spot my error I would love to know where I went wrong.
Thanks,
Zeus
I am having trouble writing values to my DS1302. I am making a clock and would like to be able to adjust the minutes and hours from the clock itself using push buttons. The code which addresses adjusting the minutes is below.
' Adjust Minutes Buttons Block
IF (MenuNum = 10) THEN
SELECT INA & 3 ' Possibilities are 00, 01, 10 and 11.
CASE = 2
GOSUB Get_Time
mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) + 1 // 60) ' Count up mod 60 using // operator
mins = ((mins / 10 << 4) + (mins // 10))
CASE = 1
GOSUB Get_Time
mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) - 1 MAX 59) ' Count down mod 60, return to 59 when value becomes 255
mins = ((mins / 10 << 4) + (mins // 10))
ENDSELECT
GOSUB Set_Time
ENDIF
I have code which sends the time to the debug and can see that the minutes value is increasing and decreasing accordingly however once the buttons are releases the time on reverts back to the original time. In short it does not seem that I am able to write this new minutes value to the DS1302.
If anyone can spot my error I would love to know where I went wrong.
Thanks,
Zeus

Comments
Yup, I'll second that! :-)
As requested.
' -----[ Subroutines - DS1302 ]-------------------------------------------- Set_RAM: index = CWPr ' Write Protect Register ioByte = WPr0 ' Clear Write Protect GOSUB RTC_Out ' Send Command ioByte = 0 ' Address Of Alarm Minutes index = WrRam | (ioByte << 1) ' Write RAM Mode + Address ioByte = AlmMins ' Set Alarm 1 Minutes GOSUB RTC_Out ' Write Value ioByte = 1 ' Address Of Alarm Hours index = WrRam | (ioByte << 1) ' Write RAM Mode + Address ioByte = AlmHrs ' Set Alarm 1 Hours GOSUB RTC_Out ' Write Value ioByte = 2 ' Address Of Flags index = WrRam | (ioByte << 1) ' Write RAM Mode + Address ioByte = flags ' Set Flags GOSUB RTC_Out ' Write Value index = CWPr ' Write Protect Register ioByte = WPr1 ' Set Write Protect GOSUB RTC_Out ' Send Command RETURN Get_RAM: index = CWPr ' Write Protect Register ioByte = WPr1 ' Set Write Protect GOSUB RTC_Out ' Send Command ioByte = 0 ' Address Of Alarm Minutes index = RdRam | (ioByte << 1) ' Read RAM Mode + Address GOSUB RTC_In ' Get Value AlmMins = ioByte ' Restore Alarm Minutes ioByte = 1 ' Address Of Alarm Hours index = RdRam | (ioByte << 1) ' Read RAM Mode + Address GOSUB RTC_In ' Get Value AlmHrs = ioByte ' Restore Alarm Hours ioByte = 2 ' Address Of Flags index = RdRam | (ioByte << 1) ' Read RAM Mode + Address GOSUB RTC_In ' Get Value flags = ioByte ' Restore Flags RETURN RTC_Out: HIGH DS1302 ' Select DS1302 SHIFTOUT DataIO, Clock, LSBFIRST, [index, ioByte] LOW DS1302 ' Deselect DS1302 RETURN RTC_In: HIGH DS1302 ' Select DS1302 SHIFTOUT DataIO, Clock, LSBFIRST, [index] SHIFTIN DataIO, Clock, LSBPRE, [ioByte] LOW DS1302 ' Deselect DS1302 RETURN Set_Time: ' DS1302 Burst Write HIGH DS1302 ' Select DS1302 SHIFTOUT DataIO, Clock, LSBFIRST, [WrBurst] SHIFTOUT DataIO, Clock, LSBFIRST, [secs, mins, hrs, date, month, day, year, 0] LOW DS1302 ' Deselect DS1302 RETURN Get_Time: ' DS1302 Burst Read HIGH DS1302 ' Select DS1302 SHIFTOUT DataIO, Clock, LSBFIRST, [RdBurst] SHIFTIN DataIO, Clock, LSBPRE, [secs, mins, hrs, date, month, day, year] LOW DS1302 ' Deselect DS1302 clockMode = 0 ' Clear BIT7 IF hrs > $11 THEN ' AM/PM? TimeAmPm = 1 ' PM ELSE TimeAmPm = 0 ' AM ENDIF RETURNZeus
The Write Protect Bit must be cleared before any other write commands. Are you sure you set the WP bit to zero before you called Set_Time?
I have put the statement as early in the subroutine as possible and still the same result, see below. Any thoughts?
' Adjust Minutes Buttons Block IF (MenuNum = 10) THEN SELECT INA & 3 ' Possibilities are 00, 01, 10 and 11. CASE = 2 ioByte = WPr0 ' Clear Write Protect GOSUB Get_Time mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) + 1 // 60) ' Count up mod 60 using // operator mins = ((mins / 10 << 4) + (mins // 10)) ioByte = WPr1 ' Set Write Protect CASE = 1 ioByte = WPr0 ' Clear Write Protect GOSUB Get_Time mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) - 1 MAX 59) ' Count down mod 60, return to 59 when value becomes 255 mins = ((mins / 10 << 4) + (mins // 10)) ioByte = WPr1 ' Set Write Protect ENDSELECT GOSUB Set_Time ENDIFZeus
No, you need to add the following before you make any writes to the DS1302 to first clear the WP bit.
Just setting ioByte to a value doesn't clear the WP bit, you have to call the subroute RTC_Out to sent it to the DS1302. After doing that, you shouldn't have to call it again unless you set the WP bit later your program. But without seeing your entire code listing, it's hard to say what else might be going on.
I had tried that and had no luck. I will give it another go and post my results.
Thanks,
Zeus
' Adjust Minutes Buttons Block IF (MenuNum = 10) THEN SELECT INA & 3 ' Possibilities are 00, 01, 10 and 11. CASE = 2 index = CWPr ' Write Protect Register ioByte = WPr0 ' Clear Write Protect GOSUB RTC_Out ' Send Command GOSUB Get_Time mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) + 1 // 60) ' Count up mod 60 using // operator mins = ((mins / 10 << 4) + (mins // 10)) 'ioByte = WPr1 ' Set Write Protect CASE = 1 index = CWPr ' Write Protect Register ioByte = WPr0 ' Clear Write Protect GOSUB RTC_Out ' Send Command GOSUB Get_Time mins = ((mins.HIGHNIB * 10 + mins.LOWNIB) - 1 MAX 59) ' Count down mod 60, return to 59 when value becomes 255 mins = ((mins / 10 << 4) + (mins // 10)) 'ioByte = WPr1 ' Set Write Protect ENDSELECT GOSUB Set_Time ENDIFThe "Set_RAM:" code is posted above.
Zeus
You do not need an index to use the burst write mode, but you can use an index and write just the minutes if that's all you want to do.
I want to write the updated minutes value to the DS1302 in as little code space as possible. Where do you recommend that I look?
Zeus
At the beginning of your program, make sure WP is off:
You shouldn't enable (set) the WP bit anywhere after that.
Then, all you need to write just the minutes is:
I will add your code and give it a try. I'll post more tomorrow.
Zeus
That did it. I still have some refinement to do and I think that I need to add a debounce statement, but regardless that was the answer to my problems.
Thanks again,
Zeus