(23 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
[[Category:AVR Tutorials]]
 
=Basics=
 
=Basics=
  
Line 7: Line 8:
 
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.
 
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.
+
Check the [[Serial_protocol_I2C|Basics of I2C]] here, if you are not familiar with it.
For [[A5.AVR Communication Protocols:I2C, SPI|Details of I2C]], go to this tutorial.
+
For details of I2C in AVR, go through [[A5.AVR Communication Protocols:I2C, SPI|AVR Communication Protocols]] tutorial.
  
=Schematic=
+
The first thing that the MCU sends to the slave (RTC) is the device ID. The device ID for DS1307, shown below. It also tells weather we want to write to or read from the RTC.
[http://exploreembedded.com/wiki/images/4/43/Schematic_AVR_Interfacing_RTC.pdf ]
+
  
[[File:Schematic AVR Interfacing RTC.JPG|680px]]
+
{| class= "table table-striped table-bordered"
 +
|-
 +
|7||6||5||4||3||2||1||0
 +
|-
 +
|1||1||0||1||0||0||0||R/W
 +
|}
  
=Code=
+
* bit-0 is '''0''' than we '''Write''' to RTC
 +
* bit-0 is '''1'''  we '''Read''' from RTC.
  
 +
This is defined in the code as:
 
<syntaxhighlight>
 
<syntaxhighlight>
 +
#define C_Ds1307ReadMode_U8  0xD1u  // DS1307 ID
 +
#define C_Ds1307WriteMode_U8  0xD0u  // DS1307 ID
 +
</syntaxhighlight>
  
#include <avr\io.h>    // io.h contains the defnition of all ports and SFRs
+
The RTC keeps the date and time arranged in it's memory as shown below:
#include "lcd.h"         //User defined LCD library which conatins the lcd routines
+
{|class="table table-striped table-bordered"
#include "ds1307.h"    //User defined library which conatins the RTC(ds1307) routines
+
|-
 +
!ADDRESS!!FUNCTION!!RANGE
 +
|-
 +
|00h|| Seconds|| 00–59
 +
|-
 +
|01h ||Minutes ||00–59
 +
|-
 +
|02h ||Hours    ||01-12/00-24
 +
|-
 +
|03h ||Day ||01–07
 +
|-
 +
|04h|| Date|| 01–31
 +
|-
 +
|05h ||Month ||01–12
 +
|-
 +
|06h ||Year ||00–99
 +
|-
 +
|07h ||Control||
 +
|-
 +
|08h to 3Fh ||RAM|| 00h–FFh
 +
|}
  
/* start the main program */
+
Write to the addresses above we can set the time, and once we set it, we can read it any time we need.
void main()  
+
 
 +
 
 +
The address 0x07 is a control registered as described below:
 +
{|class="table table-striped table-bordered"
 +
|-
 +
|7||6||5||4||3||2||1||0
 +
|-
 +
|OUT|| 0|| 0|| SQWE||0|| 0||RS1||RS0
 +
|}
 +
We write 0x00  to Control register to disable SQW-Out. We do not use any other bits from it, so you need not worry.
 +
=Initialize=
 +
Now we can initialize the RTC with the code below
 +
<syntaxhighlight>
 +
void RTC_Init(void)
 
{
 
{
  unsigned char sec,min,hour,day,month,year;
+
    I2C_Init();                             // Initialize the I2c module.
 +
    I2C_Start();                            // Start I2C communication
  
  /* Initilize the lcd before displaying any thing on the lcd */
+
    I2C_Write(C_Ds1307WriteMode_U8);        // Connect to DS1307 by sending its ID on I2c Bus
     LCD_Init();
+
     I2C_Write(C_Ds1307ControlRegAddress_U8);// Select the Ds1307 ControlRegister to configure Ds1307
  
  /* Initilize the RTC(ds1307) before reading or writing time/date */
+
    I2C_Write(0x00);                        // Write 0x00 to Control register to disable SQW-Out
    DS1307_Init();
+
  
  /*Set the time and Date only once */
+
    I2C_Stop();                             // Stop I2C communication after initializing DS1307
  DS1307_SetTime(0x10,0x40,0x20); // 10:40:20 am
+
}
  DS1307_SetDate(0x04,0x02,0x15);  // 4th Feb 2015
+
</syntaxhighlight>
  
  /* Display "Time" on first line*/
+
=Set Date and Time=
  LCD_DisplayString("Time: ");
+
  
  /* Display "Date" on Second line*/
+
<syntaxhighlight>
  LCD_GoToLineTwo();
+
void RTC_SetDateTime(rtc_t *rtc)
  LCD_DisplayString("Date: ");
+
{
 +
    I2C_Start();                         // Start I2C communication
  
  /* Display the Time and Date continuously */  
+
    I2C_Write(C_Ds1307WriteMode_U8);      // connect to DS1307 by sending its ID on I2c Bus
  while(1)
+
     I2C_Write(C_Ds1307SecondRegAddress_U8); // Request sec RAM address at 00H
     {
+
/* Read the Time from RTC(ds1307) */  
+
        DS1307_GetTime(&hour,&min,&sec);       
+
  
/* Display the time on Firstline-7th position*/
+
    I2C_Write(rtc->sec);                    // Write sec from RAM address 00H
        LCD_GoToXY(0,6);
+
    I2C_Write(rtc->min);                    // Write min from RAM address 01H
        LCD_DisplayRtcTime(hour,min,sec);
+
    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
/* Read the Date from RTC(ds1307) */  
+
}
        DS1307_GetDate(&day,&month,&year);       
+
</syntaxhighlight>
 +
Note: The date and time read from Ds1307 will be of BCD format, like:<br/>
  
/* Display the Date on Secondline-7th position*/
+
*0x12,0x39,0x26 for 12hr,39min and 26sec.   
        LCD_GoToXY(1,6);
+
*0x15,0x08,0x47 for 15th day,8th month and 47th year
        LCD_DisplayRtcDate(day,month,year);
+
 
     }
+
=Get Date and Time=
 +
<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>
 
</syntaxhighlight>
  
[[Category:AVR Tutorials]]
+
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>
 +
 
 +
=Example=
 +
Now, let's put together the all that we have discussed in a simple example to read and show the time on character LCD.
 +
 
 +
==Hookup==
 +
[[File:Real Time Clock(DS1307) with AVR LCD RTC.png|none]]
 +
 
 +
[[File:Real Time Clock(DS1307) with AVR LCD bb.png|none]]
 +
 
 +
==Code==
 +
<html>
 +
<script src="https://gist.github.com/Xplorer001/dabc20ebd54d261f07f0.js"></script>
 +
</html>
 +
 
 +
=Schematic=
 +
[http://exploreembedded.com/wiki/images/4/43/Schematic_AVR_Interfacing_RTC.pdf ]
 +
 
 +
[[File:Schematic AVR Interfacing RTC.JPG|680px]]
 +
 
 +
[[File:Real Time Clock(DS1307) with AVR.gif|none]]
 +
 
 +
=Video Tutorial=
 +
For those of you, who would like to watch instead of read we have made a video with all the gyan.
 +
<br>
 +
{{#ev:youtubehd|-lNAmSNV2-Q|640}}
 +
 
 +
 
 +
= Downloads=
 +
Download the complete project folder from the below link:
 +
https://github.com/ExploreEmbedded/ATmega32_ExploreUltraAvrDevKit/archive/master.zip<br>
 +
 
 +
 
 +
 
 +
Have a opinion, suggestion , question or feedback about the article let it out here!
 +
{{DISQUS}}

Latest revision as of 11:47, 19 April 2016

Basics

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.

The RTC DS1307 is a handy solution to keep time all the way, when it is powered by a coin cell.

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.

Check the Basics of I2C here, if you are not familiar with it. For details of I2C in AVR, go through AVR Communication Protocols tutorial.

The first thing that the MCU sends to the slave (RTC) is the device ID. The device ID for DS1307, shown below. It also tells weather we want to write to or read from the RTC.

7 6 5 4 3 2 1 0
1 1 0 1 0 0 0 R/W
  • bit-0 is 0 than we Write to RTC
  • bit-0 is 1 we Read from RTC.

This is defined in the code as:

#define C_Ds1307ReadMode_U8   0xD1u  // DS1307 ID
#define C_Ds1307WriteMode_U8  0xD0u  // DS1307 ID

The RTC keeps the date and time arranged in it's memory as shown below:

ADDRESS FUNCTION RANGE
00h Seconds 00–59
01h Minutes 00–59
02h Hours 01-12/00-24
03h Day 01–07
04h Date 01–31
05h Month 01–12
06h Year 00–99
07h Control
08h to 3Fh RAM 00h–FFh

Write to the addresses above we can set the time, and once we set it, we can read it any time we need.


The address 0x07 is a control registered as described below:

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

We write 0x00 to Control register to disable SQW-Out. We do not use any other bits from it, so you need not worry.

Initialize

Now we can initialize the RTC with the code below

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
}

Set Date and Time

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
}

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

Get Date and Time

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;

Example

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

Hookup

Real Time Clock(DS1307) with AVR LCD RTC.png
Real Time Clock(DS1307) with AVR LCD bb.png

Code

Schematic

[1]

Schematic AVR Interfacing RTC.JPG

Real Time Clock(DS1307) with AVR.gif

Video Tutorial

For those of you, who would like to watch instead of read we have made a video with all the gyan.


Downloads

Download the complete project folder from the below link: https://github.com/ExploreEmbedded/ATmega32_ExploreUltraAvrDevKit/archive/master.zip


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