Management of the RTC DS1307 module

published: 12 November 2019 / updated 12 November 2019

Lire cette page en français

 

The real-time clock or RTC (Real Time Clock) DS1307 provides the date and time to the Arduino board via the I2C link.

Introduction

périphérique RTC DS1307 relié à une carte ARDUINO MEGA via le bus I2C

Find all the explanations on the RTC DS1307 module here:
  Module DS1307 RTC

Example of connecting the RTC DS1307 module to an ARDUINO MEGA board:

I2C bus connection diagram

Find all the explanations on the I2C bus here:
  L'interface I2C des cartes ARDUINO

Programming and using the RTC DS1307 module via the I2C bus

addr-ds1307 constant contains the hexadecimal value $68.

This value was determined by analyzing the connected and active modules on our I2C bus, via the word i2c.detect available here: L'interface I2C des cartes ARDUINO

\ i2c device address 
$68 constant addr-ds1307 

The word i2c! passes a byte on the I2C bus and rejects the status flag of transmission:

: i2c! ( c ---) 
    i2c.c! drop ; 

The word ds1307.addr! passes a byte to our RTC DS1307 module:

: ds1307.addr! ( c -- )  \ Set ds1307 register address 
    i2c.init  
    addr-ds1307  i2c.addr.write drop 
    i2c! i2c.stop 
  ; 

Initialization and recovery date and time

The word time! passes the date and time information to the RTC DS1307 module:

: time! ( Y M D d HH MM SS  -- ) 
    i2c.init addr-ds1307  i2c.addr.write drop 
    0 i2c!  
    i2c! i2c! i2c!  
    i2c! i2c! i2c! i2c! 
    i2c.stop 
; 

The word time@ retrieves the date and time information from the RTC module DS1307.

: time@ ( -- S M H d D M Y ) 
    0 ds1307.addr! 
    addr-ds1307 i2c.addr.read drop 
    i2c.c@.ack i2c.c@.ack i2c.c@.ack 
    i2c.c@.ack i2c.c@.ack i2c.c@.ack i2c.c@.nack 
    i2c.stop 
; 

ATTENTION: information transmitted and received to and from RTC module DS1307 must be in BCD format.

BCD format

The BCD format is a format that encodes in one byte two decimal values. Example:

Chaque moitié d'octet correspond à la valeur en binaire d'un chiffre allant de 0 à 9 exclusivement. Sur un octet, on ne peut donc coder que des valeurs allant de 00 à 99.

L'encodage BCD permet de simplifer la transformation binaire vers décimal et inversement.

Le mot bin>bcd transforme une valeur binaire pure en valeur encodée en BCD.

: bin>bcd ( c -- c ) 
    #10 u/mod #4 lshift or 
  ; 

Example: 13 in pure binary is written %00001101. Once converted in BCD, 13 bin>bcd, 13 will be written as% 00010011.

If we cut in two our byte %00010011, we find %0001 at the top, therefore the number 1 of the number 13, %0011 in the lower part, so the number 3 of the number 13.

Transmission date and time

This is the word set-time that we will use to transmit the date and time information to initialize the RTC DS1307 module:

: set-time ( year month date day hour min sec -- ) 
    >r >r >r >r >r >r 
\    $00 swap     \ 11 = 4.096 KHz output 00 = no output 
    bin>bcd      \ Year 0-99 
    r> bin>bcd   \ Month 
    r> bin>bcd   \ Date 
    r>           \ Day 1-7 
    r> bin>bcd   \ Hours 
    r> bin>bcd   \ Minutes 
    r> bin>bcd   \ Seconds 
    time! 
; 

The word set-time expects 7 parameters, which are in order:

The set-time word performs the necessary BCD encodings before pass the data to the word time!.

Example of use:

i2c.init 
19 11 12 2 18 06 0 set-time

From this moment, the RTC module advances its internal clock without it is necessary to intervene. You can disconnect the ARDUINO board. The RTC module DS1307 will restore the correct date and time when the ARDUINO board is restarted.

Retrieving and decoding the time and date

The word bcd>bin transforms BCD encoded data into pure binary:

: bcd>bin ( c --- c) 
    #16 u/mod 10 * + ; 

Formatting data to display

The words that follow are used to format the data to display.

The word :## transforms 2 digits of the seconds and minutes in the format :SS and :MM. The word :## is then used in the HMS word that handles three values retrieved from the RTC DS1307 module and reconstructs the time in HH:MM:SS format.

The word DMY retrieves the data day month and year and restores the date in format DD/MM/YYYY.

: :## ( d1 --- d2 ) 
    decimal # 
    6 base ! #  decimal  
    [char] : hold   
  ; 
: HMS ( s m h --- adr len) 
    bcd>bin 3600 um* rot  bcd>bin 60 um* d+  rot bcd>bin 0 d+ 
    <#  :##  :## #s #> 
  ; 
: DMY ( d m y --- adr len) 
    bcd>bin 0 <# # # [char] 0 hold [char] 2 hold 
    2drop bcd>bin 0  [char] / hold # #  
    2drop bcd>bin 0  [char] / hold # #   
    #> 
  ; 

And finally, the word .date retrieves data from the RTC DS1307 module and displays this data in DD/MM/YYYY format HH:MM:SS

: .date ( ---) 
    time@ DMY type space  
    drop  HMS type  
  ; 

Example of running .date:

.date 12/11/2019 18:06:00 ok<#,ram> 
.date 12/11/2019 18:06:06 ok<#,ram> 
.date 12/11/2019 18:06:11 ok<#,ram> 
.date 12/11/2019 18:06:50 ok<#,ram>