Shop OBEX P1 Docs P2 Docs Learn Events
Problems writing to DS1302 — Parallax Forums

Problems writing to DS1302

ZeusZeus Posts: 79
edited 2012-10-25 15:47 in BASIC Stamp
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.
' 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

  • Tracy AllenTracy Allen Posts: 6,662
    edited 2012-10-21 16:26
    Zeus, I think we'd need to see your setTime routine.
  • xanatosxanatos Posts: 1,120
    edited 2012-10-21 16:56
    Zeus, I think we'd need to see your setTime routine.

    Yup, I'll second that! :-)
  • ZeusZeus Posts: 79
    edited 2012-10-21 17:38
    Gentlemen,

    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
      RETURN
    
    

    Zeus
  • SapphireSapphire Posts: 496
    edited 2012-10-21 19:06
    Zeus,

    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?
  • ZeusZeus Posts: 79
    edited 2012-10-23 15:33
    Sapphire,

    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
    
    ENDIF
    
    

    Zeus
  • SapphireSapphire Posts: 496
    edited 2012-10-23 16:31
    Zeus,

    No, you need to add the following before you make any writes to the DS1302 to first clear the WP bit.
      index = CWPr                          ' Write Protect Register
      ioByte = WPr0                         ' Clear Write Protect
      GOSUB RTC_Out                         ' Send Command
    

    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.
  • ZeusZeus Posts: 79
    edited 2012-10-23 16:52
    Sapphire,

    I had tried that and had no luck. I will give it another go and post my results.

    Thanks,

    Zeus
  • ZeusZeus Posts: 79
    edited 2012-10-23 18:08
    I have made the following changes, posted below, and still the same result. I am wondering if I need to make some sort of indexing statement similar to how the alarm minutes are written withing the "Set_RAM:" sub routine for the actual time minutes themselves? (Somehow this seems redundant.)
    ' 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
    
    ENDIF
    

    The "Set_RAM:" code is posted above.

    Zeus
  • SapphireSapphire Posts: 496
    edited 2012-10-23 18:39
    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.
  • ZeusZeus Posts: 79
    edited 2012-10-23 19:03
    Sapphire,

    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
  • SapphireSapphire Posts: 496
    edited 2012-10-23 19:48
    Zeus,

    At the beginning of your program, make sure WP is off:
      index = $8E                           ' Write to control register
      ioByte = 0                            ' Clear WP bit
      GOSUB RTC_Out                         ' Write value
    

    You shouldn't enable (set) the WP bit anywhere after that.

    Then, all you need to write just the minutes is:
      index = $82                           ' Write to minutes register
      ioByte = minutes                      ' Set the minutes
      GOSUB RTC_Out                         ' Write value
    
  • ZeusZeus Posts: 79
    edited 2012-10-23 20:13
    Thanks Sapphire,

    I will add your code and give it a try. I'll post more tomorrow.

    Zeus
  • ZeusZeus Posts: 79
    edited 2012-10-25 15:47
    Thanks Sapphire,

    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
Sign In or Register to comment.