News:

Let's find out together what makes a PIC Tick!

Main Menu

PCF8523 RTC 'Funny' with reading date

Started by Clayton, Apr 21, 2024, 07:27 AM

Previous topic - Next topic

Clayton

Hi all,

I am busy using a PCF8523 RTC chip in my design, and have converted the DS1307.INC file to use it's routines.
Everything appeared to work just fine, until the date changed from the 19th to the 20th of the month.
When this occurs, the Day is read as '00' instead of '20'.
The other strange thing is that all other time/date values, when they reach 20+ read correctly.

Any clues as to the cause of this 'Day' reading error.

Much appreciate any help on this as I am totally befuddled :)

Thanks in advance.

Frizie

Post the program-code here so we can take a look.
Ohm sweet Ohm | www.picbasic.nl

Clayton

#2
$define PCF8523T_SCL_Pin PORTB.4
$define PCF8523T_SDA_Pin PORTB.1

Include "PCF8523T.inc"

Device = 16F88
Declare Xtal 8

Config1 INTRC_IO, WDT_OFF, PWRTE_OFF, MCLR_ON, BODEN_OFF, LVP_OFF, CPD_OFF,_
        WRT_PROTECT_OFF, DEBUG_OFF, CCP1_RB3, CP_OFF
Config2 IESO_OFF, FCMEN_OFF

OSCCON = %01110010          'Dec 114 - Internal 8MHz Oscillator Enable
SSPCON = %00111011          ' Enable I2C Master  was %00101011
SSPSTAT = %00000000
TRISA = %10111111
TRISB = %11000001
RCSTA.4 = 1                'CREN Continuous Receive Enable bit
'rcsta.7 = 1                'SPEN Serial Port Enable bit
TXSTA.5 = 1                'TXEN Transmit Enable bit
TXSTA.4 = 0                'SYNC USART Mode Select bit (Asynchronous/Synchronous)
INTCON.7 = 1                'GIE bit

'Declares

'Symbol
Symbol Start_Sw = PORTA.4              ' Start PB Switch input
Input PORTA.4
Symbol RunLed = PORTA.6                ' Led output
Output RunLed
Symbol RXD = PORTB.2                    ' RS232 RXD Input
Input RXD
Symbol BO_Detect_Led = PORTB.3          ' Led output
Output BO_Detect_Led
Symbol BO1_Detect_Pin = PORTA.0
Input BO1_Detect_Pin
'Symbol BO2_Detect_Pin = PORTA.1
'Input BO2_Detect_Pin
Symbol TXD = PORTB.5                    ' RS232 TXD Output
Output TXD
Symbol SDApin = PORTB.1
Symbol SCLpin = PORTB.4
Output PORTB.4
Symbol RTC_Read = $D1              '%11010001
Symbol RTC_Write = $D0              '%11010000
Symbol EEPROM_Read = $A1            '%01010001
Symbol EEPROM_Write = $A0          '%01010000
Symbol EEPROM_SN_Read = $B1        '%01010001
Symbol EEPROM_SN_Write = $B0        '%01010001

'Dim Variables
Dim ReadCount As Word
Dim MemAddress As Word

'RTC
Dim Control1 As Byte
Dim Control2 As Byte
Dim Control3 As Byte
Dim pDay As Byte
Dim pMonth As Byte
Dim pYear As Byte
Dim pHour As Byte
Dim pMinute As Byte
Dim pSecond As Byte
Dim pWeekDay As Byte
'pWeekDay = 0    'Not currently used
'Dim Correction As SByte
'Correction = 128            ' Time error correction value
Dim DID0 As Word        'Device Unique ID Serial Number (128 bit)
Dim DID1 As Word        'Device Unique ID Serial Number
Dim DID2 As Word        'Device Unique ID Serial Number
Dim DID3 As Word        'Device Unique ID Serial Number
Dim DID4 As Word        'Device Unique ID Serial Number
Dim DID5 As Word        'Device Unique ID Serial Number
Dim DID6 As Word        'Device Unique ID Serial Number
Dim DID7 As Word        'Device Unique ID Serial Number

'Miscellaneous
Dim Command As Byte
Dim LoggingFlag As Bit
Dim i As Word
Dim j As Word
Dim DandT_Set As Byte
'    DandT_Set = $FF
'EWrite $00, [DandT_Set]
Dim Baudmode As Word
    Baudmode = 84    '84 = 9600 Baud
Dim PulseWidth As Word
    PulseWidth = 0

PCF8523T_WriteRegister($00,%10000001)      'Control 1 Register - Correction Enabled (b0)
PCF8523T_WriteRegister($01,%00000000)      'Control 2 Register
PCF8523T_WriteRegister($02,%00000000)      'Control 3 Register
DelayMS 10
PCF8523T_WriteRegister($0E,%10000000)      'Mode 1 RTC Correction


WarmStart:

Low BO_Detect_Led  'B/O Led off to start with
Low RunLed
Command = ""
MemAddress = 0
ReadCount = ERead $01
LoggingFlag = 0

DID()

'************************************************************************************
' MAIN
'************************************************************************************
Main:
    GetTimeAndDate()
'    If RTC_Day >= 20 Or RTC_Day <= 30 Then
'        RTC_Day = (RTC_Day + 20)
'    EndIf
    SerOut TXD, Baudmode, [ Dec2 RTC_Day, "/", Dec2 RTC_Month, "/", Dec2 RTC_Year, " - ", Dec2 RTC_Hour, ":", Dec2 RTC_Minute, ":", Dec2 RTC_Second, 10]
MainFollow:
    SerOut TXD, Baudmode, [ "Ready...", 10, 10]
    SerIn RXD, Baudmode, [Command]
    While Command = ""
        SerIn RXD, Baudmode, [Command]
    Wend

    Select Command
        Case = "t"  ' Get New RTC Time and Date settings
'            DandT_Set = ERead $00
'            DelayMS 10           
'            If DandT_Set = $00 Then
Update:
                SerOut TXD, Baudmode, [ "Ready to receive Time and Date settings...", 10]
                SerIn RXD, Baudmode, [Dec2 pWeekDay, Dec2 pDay, Dec2 pMonth, Dec2 pYear, Dec2 pHour, Dec2 pMinute, Dec2 pSecond]
                PCF8523T_WriteTime(pHour, pMinute, pSecond)
                DelayMS 10
                PCF8523T_WriteDate(pWeekDay, pDay, pMonth, pYear)
                DelayMS 10
                GetTimeAndDate()
               
                'Fudge to correct for non-20's being shown
'                If RTC_Day >= 20 Or RTC_Day <= 30 Then
'                    RTC_Day = (RTC_Day + 20)
'                EndIf
               
                'Show what has been configured in the RTC
                SerOut TXD, Baudmode, [ "SET - ", Dec2 RTC_Day, "/", Dec2 RTC_Month, "/", Dec2 RTC_Year, " - ", Dec2 RTC_Hour, ":", Dec2 RTC_Minute, ":", Dec2 RTC_Second, 10]
                DelayMS 250
                DandT_Set = $01
                EWrite $00, [DandT_Set]
'            else
'            'If DandT_Set = $01 then
'                SerOut TXD, Baudmode, [ "Do you want to overide the current time & date settings?", 10]
'                SerIn RXD, Baudmode, [Command]
'                If Command = "y" Then
'                    GoTo Update
'                Else
'                    GoTo MainFollow
'                EndIf
'            EndIf
           
        Case = "r"  ' Read current RTC Time and Date settings
            GetTimeAndDate()

        Case = "d"  ' Send Logged Data
            SendData()
            GoTo MainFollow
           
        Case = "b"    ' Begin Logging
                LoggingFlag = 1
                ReadCount = ERead $01
                MemAddress = 0
                While Command = "b"
                    SerOut TXD, Baudmode, [ "Logging STARTED...", 10]
                    High RunLed
Logging:
                    Do
                        PulseWidth = PulseIn BO1_Detect_Pin, 0
                        If PulseWidth = 0 Then
                            SerOut TXD, Baudmode, [ "NO B/O...or B/O period > 0.367mS", 10]
                            GoTo JumpOver
                        Else
                            High BO_Detect_Led
                            ReadCount = ReadCount + 1
                            EWrite $01, [ReadCount]                          ' Store last ReadCount update
                            GetTimeAndDate()
                            I2COut SDApin, SCLpin, EEPROM_Write, MemAddress, [RTC_Day, RTC_Month, RTC_Year, RTC_Hour, RTC_Minute, RTC_Second, PulseWidth] ' Total of 8 Bytes storedy
                            Low BO_Detect_Led
                            PulseWidth = 0  'Reset PulseWidth
                            MemAddress = MemAddress + 8
                            If MemAddress > 8192 Then MemAddress = 0    'Restart from beggining of memory if end reached.
                        EndIf
                    Loop While PulseWidth = 0
JumpOver:
                    SerOut TXD, Baudmode, ["... Timeout (1s) 'x + Enter' to Exit Logging...", 10]
                    SerIn RXD, Baudmode, 1500, CarryOn, [Command]
                    SerOut TXD, Baudmode, ["... Timeout end ...", 10]
CarryOn:
                    If Command = "x" Then
                        LoggingFlag = 0
                        SerOut TXD, Baudmode, [ 10, "Logging STOPPED...", 10]
                        Low RunLed
                        GoTo MainFollow
                    Else
                        GoTo Logging
                    EndIf
                Wend
        Case "i"
            DID()
            SerOut TXD, Baudmode, [ "Read Count = ", Dec ReadCount, 10]
            GoTo MainFollow
        Case "q"
            SerOut TXD, Baudmode, [ 10, "Doing Warmstart...", 10]
            GoTo WarmStart
           
        Case Else
            SerOut TXD, Baudmode, [ "Command not recognised. Please re-enter", 10]
            GoTo MainFollow

    EndSelect
    GoTo WarmStart

Proc GetTimeAndDate()
    PCF8523T_ReadDate()
    PCF8523T_ReadTime()
EndProc

Proc DID()
    I2COut SDApin, SCLpin, EEPROM_SN_Write, [$80]      'Required Dummy Write for correct SN start address location to be selected - %00001000/00000000
    DelayMS 10
    I2CIn SDApin, SCLpin, EEPROM_SN_Read, [DID0, DID1, DID2, DID3, DID4, DID5, DID6, DID7]  'Retrieve 128 bit SN (UNIQUE)
    DelayMS 10
    SerOut TXD, Baudmode, [ 10, "DID: ", Dec5 DID0, Dec5 DID1, Dec5 DID2, Dec5 DID3, 10]    ', Dec5 DID4, Dec5 DID5, Dec5 DID6, Dec5 DID7, 10]
EndProc

Proc SendData()
    ' EEPROM capacity is 8192 x 8 bytes (64K)
    If ReadCount = 0 Then
        GoTo NoData
    EndIf
    DID()  'Send Device ID Serial Number
    MemAddress = 0
    SerOut TXD, Baudmode, ["ReadCount = ",Dec ReadCount, 10]
    For i = 1 To ReadCount
            I2CIn SDApin, SCLpin, EEPROM_Read, MemAddress, [pDay, pMonth, pYear, pHour, pMinute, pSecond, PulseWidth] 'Total 8 bytes read (PulseWidth is Word length, i.e. 2 bytes)
            PulseWidth = PulseWidth * 5
            SerOut TXD, Baudmode, [ Dec2 pDay, Dec2 pMonth, Dec2 pYear, ",", Dec2 pHour, Dec2 pMinute, Dec2 pSecond,  ",", Dec6 PulseWidth, " uSecs", 10]
            DelayMS 1
            MemAddress = MemAddress + 8
    Next i
    DelayMS 100
    SerOut TXD, Baudmode, [ "Finished - Erase Data ? (y/n)", 10]
    SerIn RXD, Baudmode, [Command]
    While Command = ""
        SerIn RXD, Baudmode, [Command]
    Wend
    If Command = "y" Then
        ReadCount = ERead $01  'Retrieve last ReadCount value
        For i = 0 To ReadCount * 8        ' Erase current EEPROM data
            I2COut SDApin, SCLpin, EEPROM_Write, i, [$FF]
        Next i
        ReadCount = 0          'Reset ReadCount
        EWrite $01, [ReadCount]  'Reset stored value
        SerOut TXD, Baudmode, [ 10, "Deleted...", 10]
        GoTo Finished
    ElseIf Command = "n" Then
        SerOut TXD, Baudmode, [ 10, "Nothing Deleted...", 10]
        GoTo Main
    EndIf
NoData:
    DID()  'Send Device ID Serial Number
    SerOut TXD, Baudmode, [ 10, "No Data Logged...", 10]
Finished:
EndProc

End

**************************************
Amended DS1307.INC file........
**************************************

$ifndef _PCF8523T_INC_
$define _PCF8523T_INC_



$ifndef PCF8523T_SCL_Pin
    $define PCF8523T_SCL_Pin PORTB.0          ' SCL connected to this pin
    $SendWarning "The $define PCF8523T_SCL_Pin is missing from the main program. Defaulting to using PORTB.0 - Please CHECK!!!"
$endif
$ifndef PCF8523T_SDA_Pin
    $define PCF8523T_SDA_Pin PORTB.1          ' SDA connected to this pin
    $SendWarning "The $define PCF8523T_SDA_Pin is missing from the main program. Defaulting to using PORTB.1 - Please CHECK!!!"
$endif
'
' Global Time variables
'
    Dim RTC_Second As Byte                  ' Second (0..59)
    Dim RTC_Minute As Byte                  ' Minute (0..59)
    Dim RTC_Hour  As Byte                  ' Hour  (0..11 or 0..23)
'
' Global Date variables
'
    Dim RTC_Day      As Byte              ' Date  (0..31)
    Dim RTC_Month    As Byte              ' Month (1..12)
    Dim RTC_Year      As Byte              ' Year  (0..99)
    Dim RTC_DayOfWeek As Byte              ' Day of the week (1..7)
'    Dim RTC_DayName As String * 9 Heap      ' Holds the name of the day
'    Dim RTC_MonthName As String * 9 Heap    ' Holds the name of the month
'
' Parameter variable
'
    Dim PCF8523T_bValue As Byte
'
' PCF8523T register addresses
'
    $define cRTC_DEV_ADDR  $D0        ' PCF8523T device Address (Write)
    $define cRTC_TIME      $03        ' Address for time
    $define cRTC_WDAY      $07        ' Address for day of week number
    $define cRTC_DATE      $06        ' Address for date
    $define cRTC_CONTROL  $00        ' Address for control byte
'    $define cRTC_NVRAM    $0F        ' NVRAM start
'    $define cRTC_NVRAM_MAX $13        ' NVRAM address max (56 decimal???)
'
' Values - used in calls to PCF8523T_ReadControl() and PCF8523T_WriteControl()...
'
    $define cRTC_SQWE      $10        ' Square Wave enable
    $define cRTC_SQWF_1HZ  $00        ' Square Wave frequency  1Hz
    $define cRTC_SQWF_4KHz  $01        ' Square Wave frequency  4.096KHz
    $define cRTC_SQWF_8KHz  $02        ' Square Wave frequency  8.192KHz
    $define cRTC_SQWF_32KHz $03        ' Square Wave frequency 32.768KHz
    $define cRTC_SQWOUT_H  $80        ' Set Square Wave output to high when disabled

$ifndef False
    $define False 0
$endif
$ifndef True
    $define True 1
$endif

'----------------------------------------------------------------------------
' Convert a packed BCD (Binary Coded Decimal) value to a decimal value
' Input    : pValue holds the BCD value to convert to decimal
' Output    : pResult holds the decimal value
' Notes    : None
'
Proc PCF8523T_BCDToDec(pValue As PCF8523T_bValue), Byte
    Result = (pValue >> 4) * 10
    Result = Result + (pValue & $0F)  '
EndProc

'----------------------------------------------------------------------------
' Convert a decimal value to packed BCD (Binary Coded Decimal) value
' Input    : pValue holds the decimal value to convert to BCD
' Output    : pResult holds the packed BCD value
' Notes    : None
'
Proc PCF8523T_DecToBCD(pValue As PCF8523T_bValue), Byte
    Result = ((pValue / 10) << 4)
    Result = Result | (pValue // 10)    ' 21 / 10 remainder 1
EndProc

'----------------------------------------------------------------------------
' Read a PCF8523T register ($00..$3F)
' Input    : pAddress holds the address of the register
' Output    : pResult holds the byte read from the register
' Notes    : None
'
Proc PCF8523T_ReadRegister(pAddress As Byte), Byte
    I2CIn PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, pAddress, [Result]
EndProc

'----------------------------------------------------------------------------
' Write to a PCF8523T register ($00..$3F)
' Input    : pAddress holds the address of the register
'          : pData holds the byte to write to the register
' Output    : None
' Notes    : None
'
Proc PCF8523T_WriteRegister(pAddress As Byte, pData As Byte)
    I2COut PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, pAddress,[pData]
EndProc

'----------------------------------------------------------------------------
' Read the RTC control byte ($07)
' Input    : None
' Output    : pResult holds the byte read from the register
' Notes    : See the control constants cRTC_SQWXXXX above
'
$define PCF8523T_ReadControl() PCF8523T_ReadRegister(cRTC_CONTROL)

'----------------------------------------------------------------------------
' Write the RTC Control byte ($07)
' Input    : pData holds the byte to write to the register
' Output    : None
' Notes    : See the control constants cRTC_SQWXXXX above
'
$define PCF8523T_WriteControl(pData) I2COut PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_CONTROL,[pData]

'----------------------------------------------------------------------------
' Write a byte to Non-Volatile RAM
' Input    : pAddress holds the Non-Volatile RAM address
'          : pData holds the byte to write to Non-Volatile RAM
' Output    : None
' Notes    : The RAM is physically located at
'          : $08..$3F - this routine uses address $00..$37 (56 bytes)
'
$define PCF8523T_WriteByte(pAddress, pData) '
    If pAddress < cRTC_NVRAM_MAX Then    '
        PCF8523T_WriteRegister(pAddress + cRTC_NVRAM, pData) '
    EndIf

'----------------------------------------------------------------------------
' Read a byte from Non-Volatile RAM
' Input    : pAddress holds the Non-Volatile RAM address
' Output    : Returns holding the byte read from NV RAM
' Notes    : The RAM is physically located at
'          : $08..$3F - this routine uses address $00..$37 (56 bytes)
'
Proc PCF8523T_ReadByte(pAddress As Byte), Byte
    Result = PCF8523T_ReadRegister(pAddress + cRTC_NVRAM)
EndProc

'----------------------------------------------------------------------------
' Read the Time
' Input    : None
' Output    : Variable RTC_Second holds the seconds value (in decimal)
'          : Variable RTC_Minute holds the minutes value (in decimal)
'          : Variable RTC_Hour holds the hours value (in decimal)
' Notes    : None
'
Proc PCF8523T_ReadTime()
    I2CIn PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_TIME, [RTC_Second, RTC_Minute, RTC_Hour]

    RTC_Second = PCF8523T_BCDToDec(RTC_Second)      ' Convert the Seconds value to decimal
    RTC_Minute = PCF8523T_BCDToDec(RTC_Minute)      ' Convert the Minutes value to decimal
    RTC_Hour  = PCF8523T_BCDToDec(RTC_Hour)        ' Convert the Hours value to decimal
EndProc

'----------------------------------------------------------------------------
' Read the Date
' Input    : None
' Output    : Variable RTC_DayOfWeek holds the week day value (in decimal)
'          : Variable RTC_Day holds the days value (in decimal)
'          : Variable RTC_Month holds the months value (in decimal)
'          : Variable RTC_Year holds the years value (in decimal)
' Notes    : None
'
Proc PCF8523T_ReadDate()
    I2CIn PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_WDAY, [RTC_DayOfWeek, RTC_Day, RTC_Month, RTC_Year]

    RTC_DayOfWeek = PCF8523T_BCDToDec(RTC_DayOfWeek)  ' Convert the WeekDay value to decimal
    RTC_Day      = PCF8523T_BCDToDec(RTC_Day)        ' Convert the Days value to decimal
    RTC_Month    = PCF8523T_BCDToDec(RTC_Month)      ' Convert the Months value to decimal
    RTC_Year      = PCF8523T_BCDToDec(RTC_Year)      ' Convert the Years value to decimal
EndProc

'----------------------------------------------------------------------------
' Set the Time
' Input    : pHour holds the hours value (in decimal)
'          : pMinute holds the minutes value (in decimal)
'          : pSecond holds the seconds value (in decimal)
' Output    : None
' Notes    : None
'
Proc PCF8523T_WriteTime(pHour As RTC_Hour, pMinute As RTC_Minute, pSecond As RTC_Second)
    RTC_Second = PCF8523T_DecToBCD(pSecond)          ' Convert the Seconds value to decimal
    RTC_Minute = PCF8523T_DecToBCD(pMinute)          ' Convert the Minutes value to decimal
    RTC_Hour  = PCF8523T_DecToBCD(pHour)            ' Convert the Hours value to decimal

    I2COut PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_TIME, [RTC_Second, RTC_Minute, RTC_Hour]
EndProc

'----------------------------------------------------------------------------
' Set the Date
' Input    : pDayOfWeek holds the week day value (in decimal)
'          : pDay holds the days value (in decimal)
'          : pMonth holds the months value (in decimal)
'          : pYear holds the years value (in decimal)
' Output    : None
' Notes    : None
'
Proc PCF8523T_WriteDate(pDayOfWeek As RTC_DayOfWeek, pDay As RTC_Day, pMonth As RTC_Month, pYear As RTC_Year)

    RTC_DayOfWeek = PCF8523T_DecToBCD(pDayOfWeek)    ' Convert the WeekDay value to BCD
    RTC_Day      = PCF8523T_DecToBCD(pDay)          ' Convert the Days value to BCD
    RTC_Month    = PCF8523T_DecToBCD(pMonth)        ' Convert the Months value to BCD
    RTC_Year      = PCF8523T_DecToBCD(pYear)          ' Convert the Years value to BCD

    I2COut PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_WDAY, [RTC_DayOfWeek, RTC_Day, RTC_Month, RTC_Year]
EndProc

'----------------------------------------------------------------------------
' Return the name of the day
' Input    : pDayOfWeek holds the day value 1 to 7 (Sunday to Saturday)
' Output    : RTC_DayName holds a string containing the day's name
' Notes    : None
'
Proc PCF8523T_Get_DayName(pDayOfWeek As PCF8523T_bValue), RTC_DayName
    Select pDayOfWeek
        Case 1
            Result = "Sunday"
        Case 2
            Result = "Monday"
        Case 3
            Result = "Tuesday"
        Case 4
            Result = "Wednesday"
        Case 5
            Result = "Thursday"
        Case 6
            Result = "Friday"
        Case 7
            Result = "Saturday"
    EndSelect
EndProc

'----------------------------------------------------------------------------
' Return the name of the month
' Input    : pMonth holds the month value 1 to 12 (January to December)
' Output    : RTC_MonthName holds a string containing the month's name
' Notes    : None
'
Proc PCF8523T_Get_MonthName(pMonth As PCF8523T_bValue), RTC_MonthName
    Select pMonth
        Case 1
            Result = "January"
        Case 2
            Result = "February"
        Case 3
            Result = "March"
        Case 4
            Result = "April"
        Case 5
            Result = "May"
        Case 6
            Result = "June"
        Case 7
            Result = "July"
        Case 8
            Result = "August"
        Case 9
            Result = "September"
        Case 10
            Result = "October"
        Case 11
            Result = "November"
        Case 12
            Result = "December"
    EndSelect
EndProc

'----------------------------------------------------------------------------
' Detect the PCF8523T
' Input    : None
' Output    : Returns holding 1 if the PCF8523T is available
' Notes    : Uses the Ack return for confirmation
'          : This procedure assumes that there is only 1 I2C device attached to the bus
'
Proc PCF8523T_Present(), Bit
    I2CIn PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_TIME, [WREG]
    Result = ~SRbits_C
EndProc

'----------------------------------------------------------------------------
_PCF8523T_Main:

Clayton

Hope the above helps.....
Thanks for getting back to me.

Frizie

#4
Try to make the program much smaller and focus on the part of the clock where you think the problem is.
That way you can find the cause much sooner.
Is the problem in reading out the clock, in sending the clock data to the readout part (a PC?) or is it perhaps not here at all but in the readout part (a PC program)?
If you have a separate LCD (e.g. 2x16 display) makes this a lot easier to debug.

But think of something like something as underneath (attention this is not a working program, it is not complete and is for the PCF8563, not the PCF8523)
A program that is only about controlling and reading the PCF and leaves out everything else, purely to keep your program clear and exclude everything else.

Dim pcfData  As Byte 
Dim pcfDataX As Byte           'Comparison variable
Dim id1      As Bit

pcfAdr  = %10100010 (?)        'fill in the address from the PCF8563

pcfData = %00100000
BusOut pcfAdr, 0, [pcfData]    'Run the clock   
pcfData = 0
BusOut pcfAdr, 1, [pcfData]    'Run the clock
pcfData = 55                   'Set seconds to 55
BusOut pcfAdr, 2, [pcfData]    'Seconds
pcfData = 1                    'Set minutes to 1
BusOut pcfAdr, 3, [pcfData]    'Minutes
BusOut pcfAdr, 4, [pcfData]    'Hours
BusOut pcfAdr, 5, [pcfData]    'Day
BusOut pcfAdr, 6, [pcfData]    'Weekday
BusOut pcfAdr, 7, [pcfData]    'Month
BusOut pcfAdr, 8, [pcfData]    'Year

id1 = 0

Do

  BusIn pcfAdr, 2, [pcfData]

  pcfData     = ((pcfData >> 4) * 10) + (pcfData & 15) 
  If pcfData != pcfDataX Then
    Print Dec pcfData
    pcfDataX  = pcfData
  EndIf
 
  DelayMS 10
  If id1 = 0 Then
    BusOut pcfAdr, 0, [%00000000]
    id1  = 1
  EndIf

Loop

Ohm sweet Ohm | www.picbasic.nl

Clayton

Thanks for the quick reply Frizie.
Appreciated.
I have tried various things to nail down the problem (as can be seen I have sent data to the COM port at numerous places).
I have tried checking the data at each stage of reading/writing/converting, and all are good....????
The strange thing is that the 'Day' value follows all the same routines/paths as all the other parameters, yet, they are not affected.....

I will give your routine above a try and see if it shows anything.

Thanks

Clayton

OK, so I have done further tests here, and it would appear that the correct data/format of data is being written to the RTC, but when that data is read back, the data is incorrect.
Will be trying to change the RTC next just in case the device I have has a faulty Days register.
Thanks for the feedback so far.

Frizie

- Try to place the next two lines nearly on top from your program:
  Declare I2C_SLOW_BUS On
  Declare I2C_BUS_SCL  On

 
- Try to place a short delay before and after the programline that reads the date.
- Do you have placed the 4k7 pull-up resistors for the I²C on the SCL and SDA lines?
- If so, try a lower value, e.g. 2k2.
Ohm sweet Ohm | www.picbasic.nl

Clayton

Hi Frizie,
  • Changed the RTC for a new one....same result :(
  • Added the lines above..... no change.
  • Added 10mS delays before and after........ no change.
  • I have increased the Pull up current (reduced Pullup resistor values) previously, as the I2C clock rising edges were slow (rounded at the top)

I copied some of the COM port info I send my debug messages to, and you can see that when it writes to the Date register, the BCD value and the DEC value are correct, but when it reads the register, straight after the update, the Day register BCD and DEC values are wrong.... The rest of the Time and Date values are all correct....


Ready to receive Time and Date settings...

WriteDate BCD RTC_Day = 00100010 <----------------------------GOOD
WriteDate DEC RTC_Day = 34 <------------------------------------GOOD
ReadDate BCD RTC_Day = 00000010 <-----------------------------BAD
ReadDate DEC RTC_Day = 02 <-------------------------------------BAD
SET - 02/04/24 - 20:07:30 <----------------------------------------ALL FIELDS CORRECT, EXCEPT FOR THE 'DAY' VALUE

DID: 03588063991232700255
ReadDate BCD RTC_Day = 00000010
ReadDate DEC RTC_Day = 02
02/04/24 - 20:07:30
Ready...

Must admit, this has got me totally lost as to where to go next.
It seems to point to the high nibble of the Day register not behaving.

Thanks again for your looking at this problem and making suggestions.
I may try to find other library routines to look at how they do the work compared to the DS1307 library routine. May give me a clue.

Thanks again.
Clayton

Frizie

Have you connected any more components to these I²C lines? e.g. an EEPROM?
Ohm sweet Ohm | www.picbasic.nl

RGV250

Hi,
I think you might be getting confused with binary and BCD. where you send 00100010 this is 34 in binary but 22 in BCD. 34 in BCD is 0011 0100 as the low nibble is the units and the high nibble is the tens.

Bob

Frizie

#11
Clayton has routines for that in his program (BCDtoDEC and DECtoBCD), so that can't be it.

19 = 0001 1001
20 = 0010 0000
21 = 0010 0001
..
29 = 0010 1001
30 = 0011 0000
31 = 0011 0001


It seems as if bit 5 does not want to become '1'.
You would almost suspect the PCF8523.
A wrong batch?

If you enter a value of 30 or 31 as the day, probably you should get a value of 10 or 11.

I once had a similar problem with the PCF8583, it would not work with a F-RAM type FM24C16B on the same I²C bus, while the PCF8583 works fine with EEPROMs such as a 24C512.
That's why my question is, do you have anything else on the I2C bus?
Ohm sweet Ohm | www.picbasic.nl

RGV250

Hi,
I saw the routine but it would depend on where he is showing the sent data, before or after the conversion.

Anyway, I think there is something more wrong than just the day, I have stripped all the rubbish out to just the clock and in Proteus the seconds are incorrect by -20 and instead of day, month, year I an getting month, year, day.

Got to go out but will have another look later.

Bob

RGV250

My other thought is are they actually BCD, the 1307 shows a separation for 10s and units, I don't think the 8523 does?

Bob

RGV250

OK, change the line in the proc to this for the correct day, month & year.
Proc PCF8523T_ReadDate()
    I2CIn PCF8523T_SDA_Pin, PCF8523T_SCL_Pin, cRTC_DEV_ADDR, cRTC_DATE, [RTC_Day, RTC_DayOfWeek, RTC_Month, RTC_Year]

It was reading from weekday as the start address and then the day and day of week were the wrong way round so it threw everything out. You will probably have to change the set time proc as well.

I will look at the seconds issue later.

BTW, they are BCD.

Bob


RGV250

#15
Hi,
For the seconds issue you need to clear bit 7 of the seconds register at start up. This the the oscillator stability flag and is set on power up.
Either that or mask it when reading / converting BCD to Dec.

Thinking about it, that probably happens when you set the time which I didn't do as Proteus uses the PC time.

Bob

Clayton

Thanks for the above, which appeared just as I was composing this response :)

Thank you gentlemen for the follow ups. Appreciated.

To clarify the previous 'log' output,
- the "WriteDate BCD RTD_Day" value shown is the value generated AFTER the DECtoBCD conversion has been performed and what is sent to the Day Register
- the "WriteDate DEC RTD_Day" value is just the decimal value of the BCD representation (for info)
- the "ReadDate BCD RTD_Day" value is the BCD value read from the Day register BEFORE it is converted to Decimal.
- the "ReadDate DEC RTD_Day" value is just the Decimal representation of the BCD value.
Hope that makes sense :)
The 8523 does separate the 10's and units in the Day register, the same as for the 1307

I ran a 'for/next' loop just incrementing the Day register value, and writting it/reading it back, and you can see where the 'funny' occurs....

WriteDate BCD RTC_Day = 00000001
ReadDate BCD RTC_Day = 00000001
ReadDate DEC RTC_Day = 01
SET - 01/04/24
WriteDate BCD RTC_Day = 00000010
ReadDate BCD RTC_Day = 00000010
ReadDate DEC RTC_Day = 02
SET - 02/04/24
WriteDate BCD RTC_Day = 00000011
ReadDate BCD RTC_Day = 00000011
ReadDate DEC RTC_Day = 03
SET - 03/04/24
WriteDate BCD RTC_Day = 00000100
ReadDate BCD RTC_Day = 00000100
ReadDate DEC RTC_Day = 04
SET - 04/04/24
WriteDate BCD RTC_Day = 00000101
ReadDate BCD RTC_Day = 00000101
ReadDate DEC RTC_Day = 05
SET - 05/04/24
WriteDate BCD RTC_Day = 00000110
ReadDate BCD RTC_Day = 00000110
ReadDate DEC RTC_Day = 06
SET - 06/04/24
WriteDate BCD RTC_Day = 00000111
ReadDate BCD RTC_Day = 00000111
ReadDate DEC RTC_Day = 07
SET - 07/04/24
WriteDate BCD RTC_Day = 00001000
ReadDate BCD RTC_Day = 00001000
ReadDate DEC RTC_Day = 08
SET - 08/04/24
WriteDate BCD RTC_Day = 00001001
ReadDate BCD RTC_Day = 00001001
ReadDate DEC RTC_Day = 09
SET - 09/04/24
WriteDate BCD RTC_Day = 00010000
ReadDate BCD RTC_Day = 00010000
ReadDate DEC RTC_Day = 10
SET - 10/04/24
WriteDate BCD RTC_Day = 00010001
ReadDate BCD RTC_Day = 00010001
ReadDate DEC RTC_Day = 11
SET - 11/04/24
WriteDate BCD RTC_Day = 00010010
ReadDate BCD RTC_Day = 00010010
ReadDate DEC RTC_Day = 12
SET - 12/04/24
WriteDate BCD RTC_Day = 00010011
ReadDate BCD RTC_Day = 00010011
ReadDate DEC RTC_Day = 13
SET - 13/04/24
WriteDate BCD RTC_Day = 00010100
ReadDate BCD RTC_Day = 00010100
ReadDate DEC RTC_Day = 14
SET - 14/04/24
WriteDate BCD RTC_Day = 00010101
ReadDate BCD RTC_Day = 00010101
ReadDate DEC RTC_Day = 15
SET - 15/04/24
WriteDate BCD RTC_Day = 00010110
ReadDate BCD RTC_Day = 00010110
ReadDate DEC RTC_Day = 16
SET - 16/04/24
WriteDate BCD RTC_Day = 00010111
ReadDate BCD RTC_Day = 00010111
ReadDate DEC RTC_Day = 17
SET - 17/04/24
WriteDate BCD RTC_Day = 00011000
ReadDate BCD RTC_Day = 00011000
ReadDate DEC RTC_Day = 18
SET - 18/04/24
WriteDate BCD RTC_Day = 00011001
ReadDate BCD RTC_Day = 00011001
ReadDate DEC RTC_Day = 19
SET - 19/04/24

WriteDate BCD RTC_Day = 00100000
ReadDate BCD RTC_Day = 00000000
ReadDate DEC RTC_Day = 00
SET - 00/04/24
WriteDate BCD RTC_Day = 00100001
ReadDate BCD RTC_Day = 00000001
ReadDate DEC RTC_Day = 01
SET - 01/04/24
WriteDate BCD RTC_Day = 00100010
ReadDate BCD RTC_Day = 00000010
ReadDate DEC RTC_Day = 02
SET - 02/04/24
WriteDate BCD RTC_Day = 00100011
ReadDate BCD RTC_Day = 00000011
ReadDate DEC RTC_Day = 03
SET - 03/04/24
WriteDate BCD RTC_Day = 00100100
ReadDate BCD RTC_Day = 00000100
ReadDate DEC RTC_Day = 04
SET - 04/04/24
WriteDate BCD RTC_Day = 00100101
ReadDate BCD RTC_Day = 00000101
ReadDate DEC RTC_Day = 05
SET - 05/04/24
WriteDate BCD RTC_Day = 00100110
ReadDate BCD RTC_Day = 00000110
ReadDate DEC RTC_Day = 06
SET - 06/04/24
WriteDate BCD RTC_Day = 00100111
ReadDate BCD RTC_Day = 00000111
ReadDate DEC RTC_Day = 07
SET - 07/04/24
WriteDate BCD RTC_Day = 00101000
ReadDate BCD RTC_Day = 00001000
ReadDate DEC RTC_Day = 08
SET - 08/04/24
WriteDate BCD RTC_Day = 00101001
ReadDate BCD RTC_Day = 00001001
ReadDate DEC RTC_Day = 09
SET - 09/04/24
WriteDate BCD RTC_Day = 00110000
ReadDate BCD RTC_Day = 00010000
ReadDate DEC RTC_Day = 10
SET - 10/04/24
WriteDate BCD RTC_Day = 00110001
ReadDate BCD RTC_Day = 00010001
ReadDate DEC RTC_Day = 11
SET - 11/04/24

Ready...

Here you see that the high nibble, when read back, is wrong when it reaches 20+.

I have raised a ticket with NXP just in case they say 'sirry iriot' you should have done this :)
Will update here if they come up with anything.

Thanks again.

Clayton

Bingo :) ;D  :D  ;D  :D  ;D
@RGV250 Your suggested amendment has done the job :)
Had to do the same change in the ReadDate and WriteDate procedures, and then it worked.
Thanks guys.
I am most grateful of your assistance with this, and well done you.

Clayton

Now outputs this....

WriteDate BCD RTC_Day = 00000001
ReadDate BCD RTC_Day = 00000001
ReadDate DEC RTC_Day = 01
SET - 01/04/24
WriteDate BCD RTC_Day = 00000010
ReadDate BCD RTC_Day = 00000010
ReadDate DEC RTC_Day = 02
SET - 02/04/24
WriteDate BCD RTC_Day = 00000011
ReadDate BCD RTC_Day = 00000011
ReadDate DEC RTC_Day = 03
SET - 03/04/24
WriteDate BCD RTC_Day = 00000100
ReadDate BCD RTC_Day = 00000100
ReadDate DEC RTC_Day = 04
SET - 04/04/24
WriteDate BCD RTC_Day = 00000101
ReadDate BCD RTC_Day = 00000101
ReadDate DEC RTC_Day = 05
SET - 05/04/24
WriteDate BCD RTC_Day = 00000110
ReadDate BCD RTC_Day = 00000110
ReadDate DEC RTC_Day = 06
SET - 06/04/24
WriteDate BCD RTC_Day = 00000111
ReadDate BCD RTC_Day = 00000111
ReadDate DEC RTC_Day = 07
SET - 07/04/24
WriteDate BCD RTC_Day = 00001000
ReadDate BCD RTC_Day = 00001000
ReadDate DEC RTC_Day = 08
SET - 08/04/24
WriteDate BCD RTC_Day = 00001001
ReadDate BCD RTC_Day = 00001001
ReadDate DEC RTC_Day = 09
SET - 09/04/24
WriteDate BCD RTC_Day = 00010000
ReadDate BCD RTC_Day = 00010000
ReadDate DEC RTC_Day = 10
SET - 10/04/24
WriteDate BCD RTC_Day = 00010001
ReadDate BCD RTC_Day = 00010001
ReadDate DEC RTC_Day = 11
SET - 11/04/24
WriteDate BCD RTC_Day = 00010010
ReadDate BCD RTC_Day = 00010010
ReadDate DEC RTC_Day = 12
SET - 12/04/24
WriteDate BCD RTC_Day = 00010011
ReadDate BCD RTC_Day = 00010011
ReadDate DEC RTC_Day = 13
SET - 13/04/24
WriteDate BCD RTC_Day = 00010100
ReadDate BCD RTC_Day = 00010100
ReadDate DEC RTC_Day = 14
SET - 14/04/24
WriteDate BCD RTC_Day = 00010101
ReadDate BCD RTC_Day = 00010101
ReadDate DEC RTC_Day = 15
SET - 15/04/24
WriteDate BCD RTC_Day = 00010110
ReadDate BCD RTC_Day = 00010110
ReadDate DEC RTC_Day = 16
SET - 16/04/24
WriteDate BCD RTC_Day = 00010111
ReadDate BCD RTC_Day = 00010111
ReadDate DEC RTC_Day = 17
SET - 17/04/24
WriteDate BCD RTC_Day = 00011000
ReadDate BCD RTC_Day = 00011000
ReadDate DEC RTC_Day = 18
SET - 18/04/24
WriteDate BCD RTC_Day = 00011001
ReadDate BCD RTC_Day = 00011001
ReadDate DEC RTC_Day = 19
SET - 19/04/24
WriteDate BCD RTC_Day = 00100000
ReadDate BCD RTC_Day = 00100000
ReadDate DEC RTC_Day = 20
SET - 20/04/24
WriteDate BCD RTC_Day = 00100001
ReadDate BCD RTC_Day = 00100001
ReadDate DEC RTC_Day = 21
SET - 21/04/24
WriteDate BCD RTC_Day = 00100010
ReadDate BCD RTC_Day = 00100010
ReadDate DEC RTC_Day = 22
SET - 22/04/24
WriteDate BCD RTC_Day = 00100011
ReadDate BCD RTC_Day = 00100011
ReadDate DEC RTC_Day = 23
SET - 23/04/24
WriteDate BCD RTC_Day = 00100100
ReadDate BCD RTC_Day = 00100100
ReadDate DEC RTC_Day = 24
SET - 24/04/24
WriteDate BCD RTC_Day = 00100101
ReadDate BCD RTC_Day = 00100101
ReadDate DEC RTC_Day = 25
SET - 25/04/24
WriteDate BCD RTC_Day = 00100110
ReadDate BCD RTC_Day = 00100110
ReadDate DEC RTC_Day = 26
SET - 26/04/24
WriteDate BCD RTC_Day = 00100111
ReadDate BCD RTC_Day = 00100111
ReadDate DEC RTC_Day = 27
SET - 27/04/24
WriteDate BCD RTC_Day = 00101000
ReadDate BCD RTC_Day = 00101000
ReadDate DEC RTC_Day = 28
SET - 28/04/24
WriteDate BCD RTC_Day = 00101001
ReadDate BCD RTC_Day = 00101001
ReadDate DEC RTC_Day = 29
SET - 29/04/24
WriteDate BCD RTC_Day = 00110000
ReadDate BCD RTC_Day = 00110000
ReadDate DEC RTC_Day = 30
SET - 30/04/24
WriteDate BCD RTC_Day = 00110001
ReadDate BCD RTC_Day = 00110001
ReadDate DEC RTC_Day = 31
SET - 31/04/24
Ready...

Frizie

Ohm sweet Ohm | www.picbasic.nl