Shop OBEX P1 Docs P2 Docs Learn Events
Did I break two Seiko S-35390A RTC devices? — Parallax Forums

Did I break two Seiko S-35390A RTC devices?

MJHanaganMJHanagan Posts: 189
edited 2015-06-23 14:46 in Propeller 1
Have been using a Propeller DNA board for a home automation project just getting underway. One of the reasons for picking this platform is the on-board RTC (Seiko S-35390A). Using the code below I managed to get the RTC running without any troubles. I have been working on the main code over a period of weeks with modest success. A few days ago I made some edits to the code that talks to a weather station and mangle the code on and off as I worked out the details of storing some data in the upper region of the Propeller's RAM (from $9600 to about $9700). After tweaking a few debugging lines in the code I downloaded the code but it would not function beyond the start routine for the RTC. After reviewing the latests edits looking for a reason why the code failed to get beyond the initialization of the RTC I decided to try a previous version of the code which work well in the past. This too choked at the start of the RTC routine. So I went even further back to the beginning where all I have is pretty much the RTC code, and this too failed at the start of the RTC. I was now convinced the RTC device got whacked so I got out the second DNA board and plugged it in and downloaded the code below. Voila, it seemed to work so I edited the code to reflect the current time and downloaded it again. As it was downloading I was unwiring the first DNA board when I noticed on the serial terminal that the code stopped working at the RTC start routine. What the heck?

Can you break two RTCs by running bad code? Is this bad code or just bad luck?
'' Seiko S-35390A RTC Driver  Version 1.0
'' Original code from OBEX ("S-35390A RTC Driver  Version 1.0 ", by Roy Eltham dated November 13, 2010)
''
'' Code modifications by MJH:
''      * includes DST features (Daylight Savings Time) - DST status
''        is stored in the RTC's "user byte":
''           0=standard time currently in effect
''           1=daylight saving time currently in effect
''         the SetDST routine checks the current date and hour to determine if a change
''         is needed and if so make the adjustment in the hour and updates the "user byte".
''      * access to sunrise and sunset times (previously stored values in EEPROM)
''      * RTC runs in fixed 24 hour mode.  Use GetHour12 for AM/PM hour
'' 
'' This uses the basic i2c driver available on the obex site
'' See end of file for terms of use.
CON
    _clkmode = xtal1 + pll16x
    _clkfreq = 80_000_000
    
    SCL       = 28           ' SCL pin of the s-35390A, SDA is assumed to be
                             ' one pin higher by the i2c driver
                             
    DeviceID  = %0110_0000   ' S-35390A device id
    
    ' S-35390A commands, these are combined with DeviceID to read or write the chip registers
    Command_Status1         = %0000_0000
    Command_Status2         = %0000_0010
    Command_DateTime        = %0000_0100
    Command_Time            = %0000_0110
    Command_Alarm1          = %0000_1000
    Command_Alarm2          = %0000_1010
    Command_ClockCorrection = %0000_1100
    Command_UserData        = %0000_1110
    
    ' these are combined (ORed) with the DeviceID and commands to
    ' indicate reading or writing of the data
    Read  = 1
    Write = 0

CON

  MemSunrise = $8000  'Location of the first long: Sunrise for day of the year 1 (1-Jan)
  MemSunset = MemSunrise + 366 * 4  'Location of the first long: Sunset for day of the year 1 (1-Jan)

  LightsPin = 1
  RFpin = 16
  
OBJ
  i2c : "basic_i2c_driver"
  pst : "Parallax Serial Terminal"
VAR
  long Status1, Status2
  long DateTime[7]        ' year(0 to 99), month, day, day of week (0 to 6), hour, minute, seconds
  long Mode24Hour         ' 0 = 12 hour mode, 1 = 24 hour mode
  long PM                 ' 0 = AM, 1 = PM
  long AlarmOccurred[2]   ' status of the 2 alarms, 0 = did not occur, 1 = did occur
  long DSTenabled         ' Daylight savings time flag (0=disabled, 1=enabled)
  long DSTadjust          ' Daylight savings adjustment hour (0=not in DST, 1=in DST)
  long DayOfYear
  
  long KeyIn
  Long LOhh, LOmm, LOss, dd, mm, yy, MemAddr
  long LightsON, LightsOFF
  long i, j, k, l, m
'  LONG LightsPin
PUB Main

  DIRA[ LightsPin ] := 1
  DIRA[ 2 ] := 1
  DIRA[ RFpin ] := 0
  
  pst.Start( 115_200 )       ' Start the terminal at 115,200 baud
  pst.HOME                 ' Clear screen and place cursor at home position
  pst.Beep
  pst.CLEAR

  pst.str(string("Seiko S-35390A Demo Program"))

  
' Start the RTC i2C function and update the time.    
  start
  
' Set mode for 24 hours
  Set24HourMode(1)
  
  pst.str(string(pst#NL,pst#NL, "The current RTC user data value is: "))
  pst.dec( GetUserData )

' Use the RTC's "user byte" to store the DST setting (0=Standard time in effect, 1=daylight saving time in effect)Set the DST  
  SetUserData( 1 )

  pst.str(string(pst#NL,pst#NL, "The current user data value is: "))
  pst.dec( GetUserData )
  
  
  '           mm, dd, yy, dow, hh, mm, ss
  'SetDateTime(6,22,15,1,12+6,57,0)

  'SetTime( 19, 17, 0 )
  
  'Update  'Read the current time from the RTC device
  
  pst.str(string(pst#NL,pst#NL, "The current clock time is: "))
  pst.rjdec(GetHour, 2, "0")
  pst.Char(":")
  pst.rjdec(GetMinutes, 2, "0") 
  pst.Char(":")
  pst.rjdec(GetSeconds, 2, "0")
  pst.Char(" ")
  IF IsPM == 0
    pst.str(string("AM  "))
  ELSE
    pst.str(string("PM  "))

  pst.str(@DayNames[GetDayOfWeek*4])
  pst.Char(" ") 
  pst.rjdec(GetDay, 2, "0")
  pst.Char("-")
  pst.str(@MonthNames[GetMonth*4])
  pst.Char("-")  
  pst.dec( GetYear )

  pst.str(string(pst#NL, "Today's sun rise time is: "))  
  pst.dec( SunriseSS( GetDayOfYear )  )
  pst.str(string(" and sunset at: "))
  pst.dec( SunsetSS( GetDayOfYear ) )

' The 90*60 corrects for 30 minutes for dusk plus 60 minutes for DST
  LightsON := SunsetSS( GetDayOfYear ) + 30 * 60 + GetUserData * 3600

  pst.str(string(pst#NL, "Lights on at: "))
  LOhh := LightsON / 60 /60
  LOmm := ( LightsON - LOhh*60*60 ) / 60
  LOss := LightsON - LOhh*60*60 - LOmm * 60
  pst.rjdec( LOhh, 2, "0" )
  pst.Char(":")
  pst.rjdec( LOmm, 2, "0" )
  pst.Char(":")
  pst.rjdec( LOss, 2, "0" )
  
  'LightsOFF := (10+12)*60*60   'Lights off at 10:00 PM 
  LightsOFF := (9+12)*60*60 + 55*60 + 0   'Lights off at 10:00 PM 

  IF ElapsedTime > LightsON AND ElapsedTime < LightsOFF
    OUTA[ LightsPin ] := 1
  ELSE
    OUTA[ LightsPin ] := 0
    
  repeat
    KeyIn := pst.rxcount
    IF KeyIn > 0
      KeyIn := pst.CharIn
      IF KeyIn == 27
        QUIT
      ELSE
        Update
        pst.str(string( pst#NL, "The time is: "))
        pst.rjdec(GetHour12, 2, "0")
        pst.Char(":")
        pst.rjdec(GetMinutes, 2, "0") 
        pst.Char(":")
        pst.rjdec(GetSeconds, 2, "0")
        pst.Char(" ")
        IF IsPM == 0
          pst.str(string("AM"))
        ELSE
          pst.str(string("PM"))
        pst.str(string( pst#NL, "Elapsed seconds since midnight: "))
        pst.dec( ElapsedTime )
        IF ElapsedTime > LightsON and ElapsedTime < LightsOFF
          pst.str(string( "  Lights are ON"))
        ELSE
          pst.str(string( "  Lights are OFF"))
       !OUTA[ 2 ]
                  
    'UserData := GetUserData
    waitcnt(cnt+clkfreq/10)
    'IF INA[ RFpin ] := 1
    '  !OUTA[ LightsPin ]
    '  !OUTA[ 2 ]
     ' waitcnt(cnt+clkfreq)  
    Update
      
    IF OUTA[ LightsPin ] == 0 AND ElapsedTime > LightsON AND ElapsedTime < LightsOFF 
      OUTA[ LightsPin ] := 1
      pst.str(string( pst#NL, "Lights turned on at "))
      pst.str( GetTimeString )
    ELSEIF OUTA[ LightsPin ] == 1 AND ( ElapsedTime < LightsON OR ElapsedTime > LightsOFF )
      OUTA[ LightsPin ] := 0
      pst.str(string( pst#NL,"Lights turned off at "))
      pst.str( GetTimeString )
    
pst.beep
pst.str(string(pst#NL,pst#NL, "All done, good-bye."))

PUB start

  i2c.Initialize(SCL)

  ' disable the alarms (int pins) 
  SetStatus2(%0000_0000)
  
  Update

  
PUB GetYear
  return DateTime[0]
  
PUB GetMonth
  return DateTime[1]
  
PUB GetDay
  return DateTime[2]
  
PUB GetDayOfWeek
  return DateTime[3]
  
PUB GetHour
  return DateTime[4]

PUB GetHour12

  IF DateTime[4] == 0
    RESULT := 12
  ELSEIF DateTime[4] >12
    RESULT := DateTime[4] - 12
  ELSE
    RESULT := DateTime[4]
     
  return RESULT
  
PUB GetMinutes
  return DateTime[5]
  
PUB GetSeconds
  return DateTime[6]
  
PUB Is24HourMode
  return Mode24Hour
  
PUB IsPM
  return PM


'' This functions tells you if the indicated alarm occured since the last time you called
'' this function. These flags are potentially set by calls to GetStatus1, Update, SetTime, or SetDateTime.
'' The flag for the indicated alarm is cleared by this function so it can be triggered again later.
'' whichAlarm should be 0 or 1
PUB DidAlarmOccur(whichAlarm)

  ' clamp incoming value
  whichAlarm := 0 #> whichAlarm <# 1
  result := AlarmOccurred[whichAlarm]
  AlarmOccurred[whichAlarm] := 0


'' state should be 0 for 12 hour mode or 1 for 24 hour mode
PUB Set24HourMode(state)

  ' clamp incoming value
  Mode24Hour := 0 #> state <# 1

  ' read the current Status1 value
  Status1 := GetStatus1

  ' update the 12/14 bit based on state
  if Mode24Hour == 1
    Status1 |= %0100_0000       ' or in the bit
    ' fix up our stored hour
    if PM == 1 AND DateTime[4] < 12
      DateTime[4] += 12
  else
    Status1 &= %1011_1111       ' mask off the bit
    ' fix up our stored hour
    if PM == 1
      DateTime[4] -= 12
      ' in 12 hour mode change hour 0 to 12
      if DateTime[4] == 0
        DateTime[4] := 12

  SetStatus1(Status1)
   
'' The hour is expected in 24 hour mode, it will be converted into 12 hour mode if you have set that mode.
'' I did this to save having another parameter passed in for the AM/PM flag which would be ignored in
'' 24 hour mode.
'' dayOfWeek is a value from 0 to 6, you can set it to whatever you want for whatever day, and the clock will just 
'' increment it each day, wrapping at 6 back to 0. You probably want to use 0 to either Sunday or Monday.
'' It only matters if you set an alarm with a dayOfWeek enabled.
PUB SetDateTime(month, day, year, dayOfWeek, hour, minutes, seconds) | index
  DateTime[0] := ConvertToBCD(year)
  DateTime[1] := ConvertToBCD(month)
  DateTime[2] := ConvertToBCD(day)
  DateTime[3] := ConvertToBCD(dayOfWeek)
  
  ' adjust hour based on 12/24 hour mode
  if Mode24Hour == 0 AND hour > 11
    hour -= 12
    DateTime[4] := ConvertToBCD(hour) | %0100_0000
  else
    DateTime[4] := ConvertToBCD(hour)
    
  DateTime[5] := ConvertToBCD(minutes)
  DateTime[6] := ConvertToBCD(seconds)

  ' write out the full date and time to the chip
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_DateTime | Write)
  repeat index from 0 to 6 
    i2c.Write(SCL, DateTime[index] >< 8)    'The ><8 reverses the order of the lower 8 bits and clears all bits above 8 to 0
  i2c.Stop(SCL)

  ' reread the date & time to fix our stored values
  Update

'' The hour is expected in 24 hour mode, it will be converted into 12 hour mode if you have set that mode.
'' I did this to save having another parameter passed in for the AM/PM flag which would be ignored in
'' 24 hour mode.
PUB SetTime(hour, minutes, seconds) | index

  ' adjust hour based on 24/12 hour mode
  if Is24HourMode == 0 AND hour > 11
    hour -= 12
    DateTime[4] := ConvertToBCD(hour) | %0100_0000 ' or in the am/pm flag (high = pm)
  else
    DateTime[4] := ConvertToBCD(hour)
    
  DateTime[5] := ConvertToBCD(minutes)
  DateTime[6] := ConvertToBCD(seconds)

  ' write out the time to the chip
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_Time | Write)
  repeat index from 4 to 6 
    i2c.Write(SCL, DateTime[index] >< 8)
  i2c.Stop(SCL)
  
  ' reread the date & time to fix our stored values
  Update
  
'' Sets the indicated alarm. The hour value is expected to be in 24 hour mode (like SetTime)
'' if dayOfWeek, hour, or minute are negative values then the alarm will not use that portion
'' of the setting.  For example, SetAlarm(0, -1, 10, 30) will have the alarm go off every morning
'' at 10:30am, SetAlarm(0, -1, -1, 15) will have the alarm go off 15 minutes after every hour of
'' every day, SetAlarm(0, -1, -1, -1) will disable the alarm.  
'' dayOfWeek is a value from 0 to 6, and corresponds with whatever you set in SetDateTime. If, when you called
'' SetDateTime, you set dayOfWeek to be 0 for Sunday, then a value of 3 here would mean Wednesday.
PUB SetAlarm(alarmIndex, dayOfWeek, hour, minutes) | Alarm[3], index

  ' Clamp to valid range
  alarmIndex := 0 #> alarmIndex <# 1

  ' Set the indicated alarm into alarm mode  
  Status2 := GetStatus2
  if alarmIndex == 0
    Status2 := Status2 & %0001_1111  ' clear the alarm 1 state flags
    Status2 := %0010_0000 | Status2  ' set the alarm 1 state flags to be in alarm mode
  else
    Status2 := Status2 & %1111_0001  ' clear the alarm 2 state flags
    Status2 := %0000_0010 | Status2  ' set the alarm 2 state flags to be in alarm mode
  SetStatus2(Status2)

  ' setup what we are going to write to the alarm registers based on the input params
  '  
  if dayOfWeek > 0
    Alarm[0] := ConvertToBCD(dayOfWeek) | %1000_0000
  else
    Alarm[0] := 0

  if hour > 0
    if Is24HourMode == 0 AND hour > 11
      hour -= 12
      Alarm[1] := ConvertToBCD(hour) | %0100_0000 ' or in the am/pm flag (high = pm)
    else
      Alarm[1] := ConvertToBCD(hour) | %1000_0000
  else
    Alarm[1] := 0

  if minutes > 0
    Alarm[2] := ConvertToBCD(minutes) | %1000_0000
  else
    Alarm[2] := 0

  ' write out the cooked alarm info to the chip
  i2c.Start(SCL)
  if alarmIndex == 0
    i2c.Write(SCL, DeviceID | Command_Alarm1 | Write)
  else
    i2c.Write(SCL, DeviceID | Command_Alarm2 | Write)
  repeat index from 0 to 2 
    i2c.Write(SCL, Alarm[index] >< 8)
  i2c.Stop(SCL)

'' These 2 functions allow you to read and write a byte of data to the clock chip that is saved across
'' power cycling the Spinneret. It will be saved as long as the SuperCap keeps the RTC chip going (days).
PUB GetUserData : result
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_UserData | Read)
  result := i2c.Read(SCL, i2c#NAK)
  i2c.Stop(SCL)
  return result

PUB SetUserData(value)
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_UserData | Write)
  i2c.Write(SCL, value)
  i2c.Stop(SCL)


PUB GetStatus1 : result
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_Status1 | Read)
  result := i2c.Read(SCL, i2c#NAK)
  i2c.Stop(SCL)

  ' check to see if either alarm occured
  ' we need to do this any time Status1 is read since reading it clears the alarm flags 
  if result & %0000_1000 <> 0
    AlarmOccurred[0] := 1
  if result & %0000_0100 <> 0
    AlarmOccurred[1] := 1

  ' Clear off the alarm flags and the reset bit (high bit).
  ' We clear the reset bit because we don't want to make it easy to accidentally reset the
  ' chip. Which could happen if we read Status1 and then use that value modified to write
  ' back to Status1.
  result &= %01110011
  
  return result

PUB SetStatus1(value)
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_Status1 | Write)
  i2c.Write(SCL, value)
  i2c.Stop(SCL)

PUB GetStatus2 : result

  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_Status2 | Read)
  result := i2c.Read(SCL, i2c#NAK)
  i2c.Stop(SCL)

  ' Clear off the low bit, this si the test bit and should always be zero.
  result &= %1111_1110
  
  return result

PUB SetStatus2(value)

  ' Clear off the low bit, this si the test bit and should always be zero.
  value &= %1111_1110
  
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_Status2 | Write)
  i2c.Write(SCL, value)
  i2c.Stop(SCL)


'' Read the full date and time from the chip. Also, updates our PM flag appropriately, and
'' updates the cached Status variables as well as the AlarmOccurred variable.
PUB Update | index, temp
  
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_DateTime | Read)
  
  ' read first 6 bytes
  repeat index from 0 to 5 
    temp := i2c.Read(SCL, i2c#ACK) >< 8

    ' the am/pm flag is valid in both 12 and 24 hour mode
    if index == 4 ' index 4 is the hour
      if temp & %0100_0000 ' check the am/pm flag bit
        PM := 1
        temp &= %1011_1111 ' mask off the am/pm flag bit
      else
        PM := 0            ' it's AM so clear the PM flag
        
    DateTime[index] := ConvertFromBCD(temp)
    
  ' read last byte   
  DateTime[6] := ConvertFromBCD(i2c.Read(SCL, i2c#NAK) >< 8)
  
  i2c.Stop(SCL)

  ' in 12 hour mode change hour 0 to 12
  'if Mode24Hour == 0 AND DateTime[4] == 0
  '  DateTime[4] := 12

  ' update cached status variables by reading the chip status
  ' this will also update the Alarm1_Occurred and Alarm2_Occurred variables
  Status1 := GetStatus1
  Status2 := GetStatus2  

  ' Update the DST values
  UpdateDST
  
'' read the detailed information about clock correction in the S-35390A datasheet
'' before using these functions
PUB SetClockCorrection(value)
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_ClockCorrection | Write)
  i2c.Write(SCL, value)
  i2c.Stop(SCL)

PUB GetClockCorrection : result
  i2c.Start(SCL)
  i2c.Write(SCL, DeviceID | Command_ClockCorrection | Read)
  result := i2c.Read(SCL, i2c#NAK)
  i2c.Stop(SCL)
  return result

PRI ConvertToBCD(value) : result
  ' convert a long to Binary Coded Decimal
  result := ((value / 10) * 16) + (value // 10) 
  return result

PRI ConvertFromBCD(value) : result
  ' convert from Binary Coded Decimal to a long
  result := ((value / 16) * 10) + (value // 16) 
  return result
  
PUB UpdateDST
{{ see http://www.nist.gov/pml/div688/dst.cfm 
As of 2007, daylight saving time in the United States
begins at 2:00 a.m. on the second Sunday of March, and
ends at 2:00 a.m. on the first Sunday of November

Note: in order for this algorithm to function properly you must use the following
day code sequence in the S35390A RTC: 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat 

}}                                          
  CASE GetMonth
    4..10 : DSTadjust := +1  'If the month is between April (4) and October (10) then it is DST 
    1..2  : DSTadjust := 0   'If the month is between December (12) and February (2) then it is not DST  
    3  :  'DST begins at 2:00 AM on the second Sunday of March
      IF ( ( GetDay + GetDayOfWeek ) >8 ) OR  ( ( GetDay + GetDayOfWeek ) == 8 AND GetHour => 2 )
        DSTadjust := +1
      ELSE
        DSTadjust := 0
    11 :  'DST ends at 2:00 a.m. on the first Sunday of November
      IF ( GetDay + GetDayOfWeek ) <7 OR ( ( GetDay + GetDayOfWeek ) ==7 AND GetHour <2 )    '<-- needs work to address 1 hour transition time
        DSTadjust := +1
      ELSE
        DSTadjust := 0
        
' Compare the DST value with the user byte value stored in the RTC. 
  IF DSTadjust <> GetUserData   'If values are not the same then a DST transition has just occured.
    IF DSTadjust == 1   'We have just transisitoned to DST so adjust clock ahead by +1 hours (2 AM --> 3 AM)
      SetTime( GetHour+1, GetMinutes, GetSeconds )
      SetUserData( 1 )  'Update the user data byte to 1 to signify the can was made to the RTC's time      
'DSTadjust = 0 so the transition was out of DST and we need adjust the clock by -1 hours
'but when we do this the next DST check will say we are back to DST time so we need
'to use a temporary user value of 2 for the next hour before setting it to 0.
    ELSEIF GetUserData == 2 AND GetHour =>2  'If we were in the transition hour and just now passed out of the 1 AM to 2 AM hour then
      SetUserData(0)                         'set the user byte value to 0 (now DST=User value=0)
    ELSE    'This is the first occurance of leaving DST so adjust the RTC hour by -1
      SetTime( GetHour-1, GetMinutes, GetSeconds )
      SetUserData( 2 )  'Update the user data byte to 2 signifying we are now in that special 1 hour transition time from 1 AM to 2 AM.  
      
RETURN DSTadjust

Pub SunriseSS( _DayOfYear )
   
  MemAddr := MemSunrise + ( _DayOfYear-1 ) * 4
  
  RESULT := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, MemAddr )
    
RETURN

Pub SunsetSS( _DayOfYear )  
' The stored sunset times (seconds past midnight) are stored as longs (4 bytes) in EEPROM memory.
' This function returns the Sunset time for the specified date.

  MemAddr := MemSunset + ( _DayOfYear-1 ) * 4
  
  RESULT := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, MemAddr )
   
RETURN

PUB GetDayOfYear | iC

  DayOfYear := 0
  iC := 0
  
  REPEAT GetMonth
    DayOfYear += DaysInMonth[iC++]

  DayOfYear += GetDay

  RETURN DayOfYear
     
PUB ElapsedTime
    
  RETURN GetHour*60*60+GetMinutes*60+GetSeconds 

PUB GetTimeString

  TimeStr[0] := GetHour12 / 10 + "0"
  TimeStr[1] := GetHour12 // 10 + "0"
  TimeStr[3] := GetMinutes / 10 + "0"
  TimeStr[4] := GetMinutes // 10 + "0"
  TimeStr[6] := GetSeconds / 10 + "0"
  TimeStr[7] := GetSeconds // 10 + "0"
  IF IsPM == 1
    TimeStr[9] := "P"
  ELSE
    TimeStr[9] := "A"

RETURN @TimeStr
    
DAT
' Sun=0, Mon=1, Tue=2, Wed=3, Thu=4, Fri=5, Sat=6
  DayNames byte "Sun", 0, "Mon", 0, "Tue", 0, "Wed", 0, "Thu", 0, "Fri", 0, "Sat", 0
' mmm=0, Jan=1, Feb=2, Mar=3, Apr=4, May=5, Jun=6, Jul=7, Aug=8, Sep=9, Oct=10, Nov=11, Dec=12
  MonthNames byte "mmm", 0, "Jan", 0, "Feb", 0, "Mar", 0, "Apr", 0, "May", 0, "Jun", 0, "Jul", 0, "Aug", 0, "Sep", 0, "Oct", 0, "Nov", 0, "Dec", 0
  DaysInMonth byte 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  TimeStr byte "hh:mm:ss xM", 0
{{
                            TERMS OF USE: MIT License                                                           

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
}}

Comments

  • tomcrawfordtomcrawford Posts: 1,126
    edited 2015-06-23 14:46
    MJHanagan wrote: »

    Can you break two RTCs by running bad code? Is this bad code or just bad luck?

    It is difficult for me to believe that it is possible to permanently damage something like a clock chip with bogus programming (although I am sure there are plenty of counter-examples).

    The data sheet is REV 4.1, which suggests the part has been in production for some time (but perhaps you got two parts from the same flakey run (or even forgeries)).

    Of course, if you have a logic analyzer, you can determine exactly how it is getting stuck.

    Page 36 of the data sheet talks about "Reset After Communication Interruption".

    I would be more inclined to look for noisy power, etc.

    Just my opinion.
  • I finally got back to this a few weeks ago and discovered that I did not break the RTC but must have had some code problems. I am reading the clock just fine now. Thanks for the help.
Sign In or Register to comment.