(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
=Basics=
+
[[Category:8051_tutorials]]
{{Box|type=l_green_light|text=
+
In this tutorial, we will see how to interface DS1307(RTC) with 8051.<br>
The Real time clock DS1307 IC basically is stand alone time clock. Well, basically we can use a micrcontroller to keep time, but the value would go off as soon as it is powered off.
+
First, we will see the internals of DS1307 and later how to read and write the date and time.<br>
  
The RTC DS1307 is a handy solution to keep time all the way, when it is powered by a coin cell.
+
=DS1307 Basics=
 +
The Real-time clock DS1307 IC basically is stand-alone time clock with following features.
 +
*Real-time clock (RTC) counts seconds, minutes, hours, date of the month, month, the day of the week, and year with leap-year compensation valid up to 2100.
 +
*The clock operates in either the 24-hour or 12-hour format with AM/PM indicator.
 +
*56-byte, battery-backed, non-volatile (NV) RAM for data storage
 +
*Two-wire(I2C) serial interface
 +
*Programmable squarewave output signal
 +
*Automatic power-fail detect and switch circuitry
 +
*Consumes less than 500nA in battery backup mode with oscillator running
 +
*Optional industrial temperature range: -40°C to +85°C
  
It is uses '''I²C''' ('''Inter-Integrated Circuit''') protocol, referred to as ''I-squared-C'', ''I-two-C'', or ''IIC'') for communication with the micrcontroller.[[Serial_protocol_I2C|Check the basics of I2C]] here, if are not familiar with it.
+
==DS1307 Pins==
}}
+
Below image shows the pin diagram and the recommended connections for DS1307.
 +
[[FILE:DS1307_PinDiagram.png]]
 +
<b>VCC, GND:</b> These pins are used to provide the power to the chip. When 5V is applied within normal limits, the device is fully accessible and data can be written and read. When a 3V battery is connected to the device and VCC is below 1.25 x VBAT, reads and writes are inhibited. However, the timekeeping function continues unaffected by the lower input voltage. As VCC falls below VBAT the RAM and timekeeper are switched over to the external power supply (nominal 3.0V DC) at VBAT.<br>
  
=Schematic=
+
<b>X1-X2:</b>Pins to connect the external 32.768kHz oscillator that provides the clock source to the chip.<br>
{{Box|type=l_green_light|text=
+
The schematic is very simple, LCD is connected in 4 bit mode.
+
The '''Serial Clock (SCL)''' from DS1307 RTC is connected to '''P3.6''' of 8051 and '''Serial Data(SDA)''' is connected to '''P3.7''' of 8051.
+
The lines are pulled up for stable voltages.
+
[[File:8051 RTC Interface.PNG|x480px]]
+
}}
+
  
=Code=
+
<b>Vbat:</b> A 3.3v Lithium battery can be connected to this pin in order to provide the power source when the external supply voltage is not available. Battery voltage must be held between 2.0V and 3.5V for proper operation.<br>
=The main program=
+
<syntaxhighlight>
+
#include <reg51.h>  
+
  
#include "lcd.h"  // xplore labz lcd library
+
<b>SCL:</b> This pin must be connected to SCL pin of the I2C Bus/Master.<br>
#include "ds1307.h"  // Xplore Labz RTC library
+
  
/* start the main program */
+
<b>SDA:</b> This pin must be connected to SDA pin of the I2C Bus/Master.<br>
void main()
+
{
+
  unsigned char sec,min,hour,day,month,year;
+
  
  /* Initilize the lcd before displaying any thing on the lcd */
+
<b>SQW/OUT:</b> When enabled, the SQWE bit set to 1, the SQW/OUT pin
    LCD_Init();
+
outputs one of four square wave frequencies (1Hz, 4kHz, 8kHz, 32kHz).
  
  /* Initilize the RTC(ds1307) before reading or writing time/date */
+
*<b>Note:</b> The SCL,SDA, and SQW are open drain and must be pulled up with appropriate pull-up resistors as shown in the image.
    DS1307_Init();
+
  
 +
==DS1307 Memory==
 +
The RTC keeps the date and time arranged in it's memory as shown below:
 +
[[FILE:DS1307_Memory_Map.png]]<br><br>
 +
{| class="table table-striped table-hover table-condensed table-bordered"
 +
|-class="info"
 +
|Control Register
 +
|-
 +
|7||6||5||4||3||2||1||0
 +
|-
 +
|OUT|| 0|| 0|| SQWE||0|| 0||RS1||RS0
 +
|}
 +
<b>OUT:</b> This bit controls the output level of the SQW/OUT pin when the square-wave output is disabled. If SQWE = 0, the logic level on the SQW/OUT pin is 1 if OUT = 1 and is 0 if OUT = 0. By default this pin will be 0.<br>
  
  /*Set the time and Date only once */
+
<b>SQWE:</b>This bit, when set to logic 1, enables the oscillator output. The frequency of the square-wave output depends on the value of the RS0 and RS1 bits. <br>
  DS1307_SetTime(0x10,0x40,0x20);  //  10:40:20 am
+
  DS1307_SetDate(0x26,0x01,0x14);  //  26th January 2014
+
  
  /* Display "Time" on first line*/
+
<b>RS1-RS0:</b>These bits control the frequency of the square-wave output when the squarewave output has been enabled.
  LCD_DisplayString("Time: ");
+
[[FILE:Ds1307_SQWE.png]]<br><br><br>
  
  /* Display "Date" on Second line*/
+
=DS1307 ID=
  LCD_GoToLineTwo();
+
{| class="table table-striped table-hover table-condensed table-bordered"
  LCD_DisplayString("Date: ");
+
|-class="info"
 +
|Ds1307 ID
 +
|-
 +
|7||6||5||4||3||2||1||0
 +
|-
 +
|1||1||0||1||0||0||0||R/W
 +
|}
 +
* <b>R/W</b> is 0  then data is <b>Written</b> to RTC
 +
* <b>R/W</b> is 1  then data is <b>Read</b> from RTC
  
  /* Display the Time and Date continously */
+
This is defined in the code as:
  while(1)
+
<syntaxhighlight>
    {
+
#define C_Ds1307ReadMode_U8  0xD1u  // DS1307 ID in read mode
  /* Read the Time from RTC(ds1307) */  
+
#define C_Ds1307WriteMode_U8  0xD0u  // DS1307 ID in write mode
        DS1307_GetTime(&hour,&min,&sec);       
+
</syntaxhighlight>
  
/* Display the time on Firstline-7th position*/
+
=Steps to initialize  DS1307=
 +
#Start the I2C communication.
 +
#Send the DS1307 address and select write operation
 +
#Send the Address of <b>Control Register</b> for sending the command.
 +
#Send the Command to Disable the SQW Out.
 +
#Stop the Communication.
 +
<syntaxhighlight>
 +
void RTC_Init(void)
 +
{
 +
    I2C_Init();                            // Initialize the I2c module.
 +
    I2C_Start();                            // Start I2C communication
  
        LCD_GoToXY(0,6);
+
    I2C_Write(C_Ds1307WriteMode_U8);       // Connect to DS1307 by sending its ID on I2c Bus
        LCD_DisplayRtcTime(hour,min,sec);
+
    I2C_Write(C_Ds1307ControlRegAddress_U8);// Select the Ds1307 ControlRegister to configure Ds1307
  
+
    I2C_Write(0x00);                        // Write 0x00 to Control register to disable SQW-Out
    /* Read the Date from RTC(ds1307) */  
+
        DS1307_GetDate(&day,&month,&year);       
+
  
/* Display the Date on Secondline-7th position*/
+
    I2C_Stop();                             // Stop I2C communication after initializing DS1307
        LCD_GoToXY(1,6);
+
}
        LCD_DisplayRtcDate(day,month,year);
+
    }
+
}
+
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
<br><br>
  
==The libraries ==
+
=Steps to Write Date and Time=
{{Box|type=l_green_light|text=
+
[[FILE:DS1307_WriteOperation.png]]
The library files and functions used in the example can be  found in [[8051_Family_C_Library]]
+
#Start the I2C communication.
You may also download the entire project code at the bottom of the page.
+
#Send the DS1307 address and select write operation
}}
+
#Send the Address of <b>SECOND</b> Register for writing the second value.
 +
#Write the Sec,min,hour,weekDay,date,month,year one by one.
 +
#Stop the Communication.
 +
<syntaxhighlight>
 +
void RTC_SetDateTime(rtc_t *rtc)
 +
{
 +
    I2C_Start();                          // Start I2C communication
  
+
    I2C_Write(C_Ds1307WriteMode_U8);      // connect to DS1307 by sending its ID on I2c Bus
 +
    I2C_Write(C_Ds1307SecondRegAddress_U8); // Request sec RAM address at 00H
  
=The Results=
+
    I2C_Write(rtc->sec);                    // Write sec from RAM address 00H
{{Box|type=l_green_light|text=
+
    I2C_Write(rtc->min);                    // Write min from RAM address 01H
The setup was tested on [http://xplorelabz.com/product_details.php?sel_prod=12 PRO_X51 8051 development board].
+
    I2C_Write(rtc->hour);                    // Write hour from RAM address 02H
[[File:{{#setmainimage:RTC Interfacing with 8051.jpeg}}|x480px]]
+
    I2C_Write(rtc->weekDay);                // Write weekDay on RAM address 03H
}}
+
    I2C_Write(rtc->date);                    // Write date on RAM address 04H
[[File:Download Icon.jpeg|thumbnail|link=http://xplorelabz.com/wiki/images/8/87/Real_time_clock_ds1307_with_8051.zip|8051_DS1307_RTC_Interfacing]]
+
    I2C_Write(rtc->month);                    // Write month on RAM address 05H
{{#widget:Facebook_Like_Box|profile=http://www.facebook.com/XploreLabz}}
+
    I2C_Write(rtc->year);                    // Write year on RAM address 06h
{{#seo:
+
 
|title=RTC Interfacing with 8051
+
    I2C_Stop();                              // Stop I2C communication after Setting the Date
|titlemode=append
+
|keywords=8051,AT89s51,at89c51,p89v51rd2,XploreLabz,DS1307, Real time Clock
+
|description= This tutorial describes interfacing Real time clock DS1307 with 8051 micrcontroller using I2C
+
}}
+
 
}
 
}
 +
</syntaxhighlight>
 +
<br><br>
 +
 +
=Steps to Read Date and Time=
 +
[[FILE:DS1307 ReadOperation.png]]
 +
#Start the I2C communication.
 +
#Send the DS1307 address and select write operation
 +
#Send the Address of <b>SECOND</b> Register for reading the second value.
 +
#Stop the Communication.
 +
#Send the DS1307 address and select Read operation
 +
#Read the Sec,min,hour,weekDay,date and month one by one and send positive acknowledgement.
 +
#Read the Year and send the Neg/No Acknowledgement.
 +
#Stop the Communication.
 +
<syntaxhighlight>
 +
void RTC_GetDateTime(rtc_t *rtc)
 +
{
 +
    I2C_Start();                            // Start I2C communication
 +
 +
    I2C_Write(C_Ds1307WriteMode_U8);        // connect to DS1307 by sending its ID on I2c Bus
 +
    I2C_Write(C_Ds1307SecondRegAddress_U8); // Request Sec RAM address at 00H
 +
 +
    I2C_Stop();                                // Stop I2C communication after selecting Sec Register
 +
 +
    I2C_Start();                            // Start I2C communication
 +
    I2C_Write(C_Ds1307ReadMode_U8);            // connect to DS1307(Read mode) by sending its ID
 +
 +
    rtc->sec = I2C_Read(1);                // read second and return Positive ACK
 +
    rtc->min = I2C_Read(1);                // read minute and return Positive ACK
 +
    rtc->hour= I2C_Read(1);              // read hour and return Negative/No ACK
 +
    rtc->weekDay = I2C_Read(1);          // read weekDay and return Positive ACK
 +
    rtc->date= I2C_Read(1);              // read Date and return Positive ACK
 +
    rtc->month=I2C_Read(1);            // read Month and return Positive ACK
 +
    rtc->year =I2C_Read(0);            // read Year and return Negative/No ACK
 +
 +
    I2C_Stop();                              // Stop I2C communication after reading the Date
 +
}
 +
</syntaxhighlight>
 +
 +
Both the above functions use a simple structure shown below for easy access
 +
<syntaxhighlight>
 +
typedef struct
 +
{
 +
  uint8_t sec;
 +
  uint8_t min;
 +
  uint8_t hour;
 +
  uint8_t weekDay;
 +
  uint8_t date;
 +
  uint8_t month;
 +
  uint8_t year; 
 +
}rtc_t;
 +
</syntaxhighlight>
 +
 +
=Hardware Connections=
 +
[[File:Ds1307 with 8051.png]]
 +
 +
=Code=
 +
Now, let's put together all that we have discussed in a simple example to read and show the time on character LCD.
 +
 +
<b>Note:</b> The date and time read from Ds1307 will be of BCD format, like:
 +
*0x12,0x39,0x26 for 12hr,39min and 26sec.   
 +
*0x15,0x08,0x47 for 15th day,8th month and 47th year
 +
<html>
 +
<script src="https://gist.github.com/SaheblalBagwan/97f4f3112414d3404c79ae2fb13295d4.js"></script>
 +
</html>
 +
 +
[[file:00Interface_RTC_with_Atmega128.gif]]
 +
<br><br>
 +
 +
=Downloads=
 +
Download the sample code and design files from [https://github.com/ExploreEmbedded/8051_DevelopmentBoard this link].
  
'''''Have a opinion, suggestion or feedback about this article, let it out here!'''''
+
Have an opinion, suggestion , question or feedback about the article let it out here!
 
{{DISQUS}}
 
{{DISQUS}}

Latest revision as of 10:14, 2 September 2016

In this tutorial, we will see how to interface DS1307(RTC) with 8051.
First, we will see the internals of DS1307 and later how to read and write the date and time.

DS1307 Basics

The Real-time clock DS1307 IC basically is stand-alone time clock with following features.

  • Real-time clock (RTC) counts seconds, minutes, hours, date of the month, month, the day of the week, and year with leap-year compensation valid up to 2100.
  • The clock operates in either the 24-hour or 12-hour format with AM/PM indicator.
  • 56-byte, battery-backed, non-volatile (NV) RAM for data storage
  • Two-wire(I2C) serial interface
  • Programmable squarewave output signal
  • Automatic power-fail detect and switch circuitry
  • Consumes less than 500nA in battery backup mode with oscillator running
  • Optional industrial temperature range: -40°C to +85°C

DS1307 Pins

Below image shows the pin diagram and the recommended connections for DS1307. DS1307 PinDiagram.png VCC, GND: These pins are used to provide the power to the chip. When 5V is applied within normal limits, the device is fully accessible and data can be written and read. When a 3V battery is connected to the device and VCC is below 1.25 x VBAT, reads and writes are inhibited. However, the timekeeping function continues unaffected by the lower input voltage. As VCC falls below VBAT the RAM and timekeeper are switched over to the external power supply (nominal 3.0V DC) at VBAT.

X1-X2:Pins to connect the external 32.768kHz oscillator that provides the clock source to the chip.

Vbat: A 3.3v Lithium battery can be connected to this pin in order to provide the power source when the external supply voltage is not available. Battery voltage must be held between 2.0V and 3.5V for proper operation.

SCL: This pin must be connected to SCL pin of the I2C Bus/Master.

SDA: This pin must be connected to SDA pin of the I2C Bus/Master.

SQW/OUT: When enabled, the SQWE bit set to 1, the SQW/OUT pin outputs one of four square wave frequencies (1Hz, 4kHz, 8kHz, 32kHz).

  • Note: The SCL,SDA, and SQW are open drain and must be pulled up with appropriate pull-up resistors as shown in the image.

DS1307 Memory

The RTC keeps the date and time arranged in it's memory as shown below: DS1307 Memory Map.png

Control Register
7 6 5 4 3 2 1 0
OUT 0 0 SQWE 0 0 RS1 RS0

OUT: This bit controls the output level of the SQW/OUT pin when the square-wave output is disabled. If SQWE = 0, the logic level on the SQW/OUT pin is 1 if OUT = 1 and is 0 if OUT = 0. By default this pin will be 0.

SQWE:This bit, when set to logic 1, enables the oscillator output. The frequency of the square-wave output depends on the value of the RS0 and RS1 bits.

RS1-RS0:These bits control the frequency of the square-wave output when the squarewave output has been enabled. Ds1307 SQWE.png


DS1307 ID

Ds1307 ID
7 6 5 4 3 2 1 0
1 1 0 1 0 0 0 R/W
  • R/W is 0 then data is Written to RTC
  • R/W is 1 then data is Read from RTC

This is defined in the code as:

#define C_Ds1307ReadMode_U8   0xD1u  // DS1307 ID in read mode
#define C_Ds1307WriteMode_U8  0xD0u  // DS1307 ID in write mode

Steps to initialize DS1307

  1. Start the I2C communication.
  2. Send the DS1307 address and select write operation
  3. Send the Address of Control Register for sending the command.
  4. Send the Command to Disable the SQW Out.
  5. Stop the Communication.
void RTC_Init(void)
{
    I2C_Init();                             // Initialize the I2c module.
    I2C_Start();                            // Start I2C communication
 
    I2C_Write(C_Ds1307WriteMode_U8);        // Connect to DS1307 by sending its ID on I2c Bus
    I2C_Write(C_Ds1307ControlRegAddress_U8);// Select the Ds1307 ControlRegister to configure Ds1307
 
    I2C_Write(0x00);                        // Write 0x00 to Control register to disable SQW-Out
 
    I2C_Stop();                             // Stop I2C communication after initializing DS1307
}



Steps to Write Date and Time

DS1307 WriteOperation.png

  1. Start the I2C communication.
  2. Send the DS1307 address and select write operation
  3. Send the Address of SECOND Register for writing the second value.
  4. Write the Sec,min,hour,weekDay,date,month,year one by one.
  5. Stop the Communication.
void RTC_SetDateTime(rtc_t *rtc)
{
    I2C_Start();                          // Start I2C communication
 
    I2C_Write(C_Ds1307WriteMode_U8);      // connect to DS1307 by sending its ID on I2c Bus
    I2C_Write(C_Ds1307SecondRegAddress_U8); // Request sec RAM address at 00H
 
    I2C_Write(rtc->sec);                    // Write sec from RAM address 00H
    I2C_Write(rtc->min);                    // Write min from RAM address 01H
    I2C_Write(rtc->hour);                    // Write hour from RAM address 02H
    I2C_Write(rtc->weekDay);                // Write weekDay on RAM address 03H
    I2C_Write(rtc->date);                    // Write date on RAM address 04H
    I2C_Write(rtc->month);                    // Write month on RAM address 05H
    I2C_Write(rtc->year);                    // Write year on RAM address 06h
 
    I2C_Stop();                              // Stop I2C communication after Setting the Date
}



Steps to Read Date and Time

DS1307 ReadOperation.png

  1. Start the I2C communication.
  2. Send the DS1307 address and select write operation
  3. Send the Address of SECOND Register for reading the second value.
  4. Stop the Communication.
  5. Send the DS1307 address and select Read operation
  6. Read the Sec,min,hour,weekDay,date and month one by one and send positive acknowledgement.
  7. Read the Year and send the Neg/No Acknowledgement.
  8. Stop the Communication.
void RTC_GetDateTime(rtc_t *rtc)
{
    I2C_Start();                            // Start I2C communication
 
    I2C_Write(C_Ds1307WriteMode_U8);        // connect to DS1307 by sending its ID on I2c Bus
    I2C_Write(C_Ds1307SecondRegAddress_U8); // Request Sec RAM address at 00H
 
    I2C_Stop();                                // Stop I2C communication after selecting Sec Register
 
    I2C_Start();                            // Start I2C communication
    I2C_Write(C_Ds1307ReadMode_U8);            // connect to DS1307(Read mode) by sending its ID
 
    rtc->sec = I2C_Read(1);                // read second and return Positive ACK
    rtc->min = I2C_Read(1);                 // read minute and return Positive ACK
    rtc->hour= I2C_Read(1);               // read hour and return Negative/No ACK
    rtc->weekDay = I2C_Read(1);           // read weekDay and return Positive ACK
    rtc->date= I2C_Read(1);              // read Date and return Positive ACK
    rtc->month=I2C_Read(1);            // read Month and return Positive ACK
    rtc->year =I2C_Read(0);             // read Year and return Negative/No ACK
 
    I2C_Stop();                              // Stop I2C communication after reading the Date
}

Both the above functions use a simple structure shown below for easy access

typedef struct
{
  uint8_t sec;
  uint8_t min;
  uint8_t hour;
  uint8_t weekDay;
  uint8_t date;
  uint8_t month;
  uint8_t year;  
}rtc_t;

Hardware Connections

Ds1307 with 8051.png

Code

Now, let's put together all that we have discussed in a simple example to read and show the time on character LCD.

Note: The date and time read from Ds1307 will be of BCD format, like:

  • 0x12,0x39,0x26 for 12hr,39min and 26sec.
  • 0x15,0x08,0x47 for 15th day,8th month and 47th year

00Interface RTC with Atmega128.gif

Downloads

Download the sample code and design files from this link.

Have an opinion, suggestion , question or feedback about the article let it out here!