News:

;) This forum is the property of Proton software developers

Main Menu

DS1307 RTC library operating from a standard 14-bit core device

Started by top204, May 17, 2023, 11:41 AM

Previous topic - Next topic

top204

Listed below is a library for the DS1307 RTC for use with a standard 14-bit core device.

The demo program is listed below:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate writing and reading a DS1307 Real Time Clock/Calendar using the DS1307 library
'
' Written by Les Johnson for the Positron8 BASIC compiler
'
    Device = 16F628A                                                ' Tell the compiler what device to compile for
    Declare Xtal = 20                                               ' Tell the compiler what frequency the device is operating at (in MHz)
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                                     ' Set the Baud rate for USART1
    Declare HRsout1_Pin  = PORTB.2                                  ' Set the pin to use for USART1 TX
'
' Setup the Alphanumeric LCD
'
    Declare LCD_DTPin = PORTB.3                                     ' The LCD's Dt4 to Dt7 lines connect to PORTB.3 to PORTB.7
    Declare LCD_ENPin = PORTA.3                                     ' Connects to the LCD's EN line
    Declare LCD_RSPin = PORTA.2                                     ' Connects to the LCD's RS line
    Declare LCD_Interface = 4                                       ' The LCD is going to use a 4-pin interface
    Declare LCD_Lines = 2                                           ' The LCD has 2 lines
    Declare LCD_Type = Alphanumeric                                 ' The LCD is an Hitachi alphanumeric type
'
' Set the pins to use for the I2C interface to the DS1307 device
'
$define DS1307_SDA_Pin PORTA.1                                      ' I2C SDA for the DS1307 connected to this pin
$define DS1307_SCL_Pin PORTA.0                                      ' I2C SCL for the DS1307 connected to this pin

    Include "DS1307_14.inc"                                         ' Load the DS1307 library routines for a standard 14-bit core device into the program
'
' Create a variable for the demo
'
    Dim bPrevSecond As Byte                                         ' Holds the previous seconds value

'----------------------------------------------------------------------------
' The main program starts here
' Read the time and date from a DS1307 device and display them on a serial terminal and an alphanumeric LCD
'
Main:
    bPrevSecond = 255                                               ' Set a previous seconds value
    Cls                                                             ' Clear the LCD's display

    DS1307_WriteDate(3, 17, 05, 23)                                 ' Write an initial date to the DS1307
    DS1307_WriteTime(9, 46, 0)                                      ' Write an initial time to the DS1307

    Do                                                              ' Create a loop
        DS1307_ReadTime()                                           ' Read the time from the DS1307
        If RTC_bSecond <> bPrevSecond Then                          ' Has the seconds value changed?
            DS1307_ReadDate()                                       ' Yes. So read the date from the DS1307
            '
            ' Transmit the ASCII date and time to a serial terminal
            '
            HRSOutLn "Time = ", Dec2 RTC_bHour, ":",_               ' \
                                Dec2 RTC_bMinute, ":",_             ' | Serially transmit the time as ASCII
                                Dec2 RTC_bSecond                    ' /

            HRSOutLn "Date = ", Dec2 RTC_bDate, ":",_               ' \
                     Dec2 RTC_bMonth, ":", _                        ' | Serally transmit the date as ASCII
                     "20", Dec2 RTC_bYear                           ' /
            '
            ' Display the date and time on the LCD
            '
            Print at 1, 5, Dec2 RTC_bHour, ":",_                    ' \
                           Dec2 RTC_bMinute, ":",_                  ' | Display the time on line 1 of the LCD
                           Dec2 RTC_bSecond                         ' /

            Print at 2, 4, Dec2 RTC_bDate, ":",_                    ' \
                           Dec2 RTC_bMonth, ":", _                  ' | Display the date on line 2 of the LCD
                           "20", Dec2 RTC_bYear                     ' /
        EndIf
        bPrevSecond = RTC_bSecond                                   ' Save this seconds value for later comparison
    Loop                                                            ' Do it forever

The DS1307 library's code listing is below. Name it "DS1307_14.inc" and place it in the same folder as the demo program using it, or in the "Includes" folder for all programs to see (C:\Users\User Name\PDS\Includes\):

$ifndef _DS1307_14_INC_
$define _DS1307_14_INC_
'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Routines to access a DS1307 Real Time Clock/Calendar via a software I2C bus and suitable for standard 14-bit core devices.
'
' Written by Les Johnson for the Positron8 Compiler.
'
' Declare the default pins used for I2Cin and I2Cout to interface to the DS1307 device
'
$ifndef DS1307_SCL_Pin
    $define DS1307_SCL_Pin PORTA.0      ' DS1307 SCL connected to this pin
    $SendWarning "The $define DS1307_SCL_Pin is missing from the main program. Defaulting to using PORTA.0"
$endif
$ifndef DS1307_SDA_Pin
    $define DS1307_SDA_Pin PORTA.1      ' DS1307 SDA connected to this pin
    $SendWarning "The $define DS1307_SDA_Pin is missing from the main program. Defaulting to using PORTA.1"
$endif
'
' DS1307 register addresses
'
     $define cRTC_DEV_ADDR  $D0         ' DS1307 device Address
     $define cRTC_TIME      $00         ' Time register
     $define cRTC_WDAY      $03         ' Day of week number register
     $define cRTC_DATE      $04         ' Date register
     $define cRTC_CONTROL   $07         ' Control byte register
     $define cRTC_NVRAM     $08         ' NVRAM start
     $define cRTC_NVRAM_MAX $38         ' NVRAM address max (56 decimal)
'
' Values - used in calls to DS1307_ReadControl() and DS1307_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
'
' Create some Time and Date variables
'
    Dim RTC_bSecond As Byte                 ' Second (0..59)
    Dim RTC_bMinute As Byte                 ' Minute (0..59)
    Dim RTC_bHour   As Byte                 ' Hour   (0..11 or 0..23)
    Dim RTC_bDate   As Byte                 ' Date  (0..31)
    Dim RTC_bMonth  As Byte                 ' Month (1..12)
    Dim RTC_bYear   As Byte                 ' Year  (0..99)
    Dim RTC_bDay    As Byte                 ' Day of the week (1..7)
'
' Create a shared parameter variable
'
    Dim DS1307_bParam1 As Byte

'----------------------------------------------------------------------------
' 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 DS1307_BCDToDec(pValue As DS1307_bParam1), 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 DS1307_DecToBCD(pValue As DS1307_bParam1), Byte
    Result = (pValue / 10) << 4
    Result = Result | (pValue // 10)
EndProc

'----------------------------------------------------------------------------
' Read a DS1307 register ($00..$3F)
' Input     : pAddress holds the address of the register
' Output    : pResult holds the byte read from the register
' Notes     : None
'
Proc DS1307_ReadRegister(pAddress), Byte
    I2CIn DS1307_SDA_Pin, DS1307_SCL_Pin, cRTC_DEV_ADDR, pAddress, [Result]
EndProc

'----------------------------------------------------------------------------
' Write to a DS1307 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 DS1307_WriteRegister(pAddress As Byte, pData As Byte)
    I2COut DS1307_SDA_Pin, DS1307_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 DS1307_ReadControl() DS1307_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 DS1307_WriteControl(pData) I2COut DS1307_SDA_Pin, DS1307_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 DS1307_WriteByte(pAddress, pData) '
    If pAddress < cRTC_NVRAM_MAX Then     '
        DS1307_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 DS1307_ReadByte(pAddress As Byte), Byte
    Result = DS1307_ReadRegister(pAddress + cRTC_NVRAM)
EndProc

'----------------------------------------------------------------------------
' Read the Time
' Input     : None
' Output    : Variable RTC_bSecond holds the seconds value (in decimal)
'           : Variable RTC_bMinute holds the minutes value (in decimal)
'           : Variable RTC_bHour holds the hours value (in decimal)
' Notes     : None
'
Proc DS1307_ReadTime()
    I2CIn DS1307_SDA_Pin, DS1307_SCL_Pin, cRTC_DEV_ADDR, cRTC_TIME, [RTC_bSecond,
                                                                     RTC_bMinute,
                                                                     RTC_bHour]
    RTC_bSecond = DS1307_BCDToDec(RTC_bSecond)      ' Convert the Seconds value to decimal
    RTC_bMinute = DS1307_BCDToDec(RTC_bMinute)      ' Convert the Minutes value to decimal
    RTC_bHour   = DS1307_BCDToDec(RTC_bHour)        ' Convert the Hours value to decimal
EndProc

'----------------------------------------------------------------------------
' Read the Date
' Input     : None
' Output    : Variable RTC_bDay holds the week day value (in decimal)
'           : Variable RTC_bDate holds the days value (in decimal)
'           : Variable RTC_bMonth holds the months value (in decimal)
'           : Variable RTC_bYear holds the years value (in decimal)
' Notes     : None
'
Proc DS1307_ReadDate()
    I2CIn DS1307_SDA_Pin, DS1307_SCL_Pin, cRTC_DEV_ADDR, cRTC_WDAY, [RTC_bDay,
                                                                     RTC_bDate,
                                                                     RTC_bMonth,
                                                                     RTC_bYear]

    RTC_bDay   = DS1307_BCDToDec(RTC_bDay)          ' Convert the WeekDay value to decimal
    RTC_bDate  = DS1307_BCDToDec(RTC_bDate)         ' Convert the Days value to decimal
    RTC_bMonth = DS1307_BCDToDec(RTC_bMonth)        ' Convert the Months value to decimal
    RTC_bYear  = DS1307_BCDToDec(RTC_bYear)         ' 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 DS1307_WriteTime(pHour As RTC_bHour, pMinute As RTC_bMinute, pSecond As RTC_bSecond)
    RTC_bSecond = DS1307_DecToBCD(pSecond)          ' Convert the Seconds value to decimal
    RTC_bMinute = DS1307_DecToBCD(pMinute)          ' Convert the Minutes value to decimal
    RTC_bHour   = DS1307_DecToBCD(pHour)            ' Convert the Hours value to decimal

    I2COut DS1307_SDA_Pin, DS1307_SCL_Pin, cRTC_DEV_ADDR, cRTC_TIME, [RTC_bSecond,
                                                                      RTC_bMinute,
                                                                      RTC_bHour]
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 DS1307_WriteDate(pDayOfWeek As RTC_bDay, pDay As RTC_bDate, pMonth As RTC_bMonth, pYear As RTC_bYear)

    RTC_bDay   = DS1307_DecToBCD(pDayOfWeek)        ' Convert the WeekDay value to decimal
    RTC_bDate  = DS1307_DecToBCD(pDay)              ' Convert the Days value to decimal
    RTC_bMonth = DS1307_DecToBCD(pMonth)            ' Convert the Months value to decimal
    RTC_bYear  = DS1307_DecToBCD(pYear)             ' Convert the Years value to decimal

    I2COut DS1307_SDA_Pin, DS1307_SCL_Pin, cRTC_DEV_ADDR, cRTC_WDAY, [RTC_bDay,
                                                                      RTC_bDate,
                                                                      RTC_bMonth,
                                                                      RTC_bYear]
EndProc

'----------------------------------------------------------------------------
_DS1307_Main:

$endif  ' _DS1307_14_INC_

A screenshot of the demo program working in the Proteus simulator is shown below:

DS1307 Controlled by a PIC16F628A.jpg