Interfacing of PIC18Fxxx with RTC(DS1307) using I2C

Updated on 2017/11/16 23:53

Syllabus

Interfacing of PIC18Fxxx with RTC(DS1306) using I2C protocol

Interfacing of PIC18Fxxx with RTC(DS1307) using I2C protocol

Real time clocks(RTC) are chips which store and keep track of time. Because of it’s precise functioning, RTCs are are incorporated in personal computers, consumer electronic and embedded devices.This chapter particularly deals with details of interfacing RTC DS1307 with PIC18F4550.

Step1-Initialization of 12C Module in Master Mode (I2C)

  1. Configure SCL and SDA pins as input through TRIS Register
  2. Calculate and Load Baud rate value in SSPADD for I2C Clock = 100Khz
    SSPADD = ((Fosc/(4-112C Clock)) - 1
  3. Enable Master I2C mode in SSPCON1 register
    SSPM3:SSPM0=1000 - I2C Master mode, clock=FOSC/(4 (SSPADD+1))
  4. Disable Slew rate control by setting SNIP bit in SSPSTAT in baud rate selected is standard (100 KHz and 1MHz)
  5. Enable I2C in SSPCON1 register by setting SSPEN bit in SSPCON1

Step-2 To write data to a slave device

  1. Send a start sequence by setting SEN bit in SSPCON2
  2. Check the start sequence transmitted
  3. Send the I'C address of the slave with the R/W bit Low (Even Address).SSPBUF = Slave Address
  4. Check the ACKSTAT from SSPSTAT
  5. Send the internal register/memory location address to which you want to write the data. SSPBUF = Address of register/memory location
  6. Send the data byte. SSPBUF = Data to be transmitted
  7. Check the ACKSTAT from SSPSTAT
  8. Send the stop sequence by setting PEN bit in SPPCON2.

Step 3-Check the stop sequence transmitted

To read data from a slave device

  1. Send a start sequence by setting SEN bit in SSPCON2
  2. Check the start sequence transmitted
  3. Send the FC address of the slave with the R/W bit Low (Even Address). SSPBUF = Slave Address
  4. Check the ACKSTAT from SSPSTAT
  5. Send the internal register/memory location address to which you want to read the data. SSPBUF = Address of register/memory location

Repeated Start Sequence

  1. Send repeated start sequence by setting RSEN bit in SSPCON2.
  2. Send the IC address of the slave with the R/W bit high (Odd Address).SSPBUF = Slave Address
  3. Read the data byte. Data = SSPBUF
  4. Send the stop sequence by setting PEN bit in SPPCON2.
  5. Check the stop sequence transmitted

Real Time Clock

Features

  • Real-time clock (RTC) counts seconds, minutes, hours, date of the month, month, day of the week, and year with leap-year compensation valid up to 2100
  • 56-byte, battery-backed, nonvolatile (NV) RAM for data storage
  • Two-wire serial interface
  • Programmable square wave 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.png

Fig. DS1307 RTC IC Pin Diagram

There is detailed notes on PIC18F4520 I2C module implementation: I2C Module In PIC18F4520

Device Addressing

The DS1307 require an 8-bit device address word following a start condition

to enable the chip for a read or write operation.

Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
1101000R/nW

The device address word consists of a mandatory one, zero sequence for the first seven most significant bits as shown above. The eighth bit of the device address is the read/write operation select bit. A read operation is initiated if this bit is high and a write operation is initiated if this bit is low. Upon a compare of the device address, the D51307 will output a zero. If a compare is not made, the chip will return to a standby state.

RTC and RAM Address Map

RTC-DS1307-Ram-space.png

Fig. RAM address space of RTC

The address map for the RTC and RAM registers of the DS1307vis as shown, The RTC registers are located in address locations

  • OOh to 07h. The RAM registers are located in address locations 08h to 3Fh. During a multi-byte access, when the address pointer reaches 3Fh, the end of RAM space, it wraps around to location OOh, the beginning of the clock space.

RTC Clock and Calender (Time Keeper Registers)

RTC-Time-Calender-Time-Keeper-Registers.png

Write Operation

write-operation.png

  • Serial data and clock are received through SDA and SCL.
  • After each byte is received an acknowledge bit is transmitted.
  • START and STOP conditions are recognized as the beginning and end of a serial transfer. Hardware performs address recognition after reception of the slave address and direction bit (see Figure ).
  • The slave address byte is the first byte received after the master generates the START condition.
  • The slave address byte contains the 7-bit DS1307 address, which is 1101000, followed by the direction bit (R/W), which for a write is 0.
  • After receiving and decoding the slave address byte, the DS1307 outputs an acknowledge on SDA. After the DS1307 acknowledges the slave address + write bit, the master transmits a word address to the DS1307.
  • This sets the register pointer on the DS1307, with the DS1307 acknowledging the transfer.
  • The master can then transmit zero or more bytes of data with the DS1307 acknowledging each byte received.
  • The register pointer automatically increments after each data byte are written.
  • The master will generate a STOP condition to terminate the data write.

Read Operation

read-operation.png

  • The first byte is received and handled as in the slave receiver mode. However, in this mode, the direction bit will indicate that the transfer direction is reversed.
  • The DS1307 transmits serial data on SDA while the serial clock is input on SCL.
  • START and STOP conditions are recognized as the beginning and end of a serial transfer (see Figure).
  • The slave address byte is the first byte received after the START condition is generated by the master. The slave address byte contains the 7-bit DS1307 address, which is 1101000, followed by the direction bit (R/W), which is 1 for a read.
  • After receiving and decoding the slave address the DS1307 outputs an acknowledge on SDA.
  • The DS1307 then begins to transmit data starting with the register address pointed to by the register pointer. If the register pointer is not written to before the initiation of a read mode the first address that is read is the last one stored in the register pointer.
  • The register pointer automatically increments after each byte are read.
  • The DS1307 must receive a Not Acknowledge to end a read.

Interfacing Diagram

I2C protocol allows multiple slave devices and master devices communicate with each other and it is used for short distance communications. It uses two signal wires to communicate with each other, SDA or data line and SCL or clock line.
SDA and SCL lines are connected to the corresponding pins in the microcontroller. I2C bus drivers are open drain so that they can’t drive corresponding signals high. This avoids bus contention when more than two devices communicate with each other and each device is trying different logic level (e.g: one device pulling high and other pulling low), thus avoiding chance to damage drivers. The signal lines have pull-up resistors to restore the signal state high when no device is using the line.

DS1307 uses a 32.768 kHz quartz crystal as the oscillator. The pins X1 and X2 are used as the oscillator pins. There is a VBAT pin for connecting the battery. The battery will provide backup in the absence of power. A CR2032 battery will provide around 7 years power backup.

RTC-DS1307-Interfacing-with-PIC18-using-I2C.png

Embedded C Program

// Interfacing I2C based RTC (DS1307) to PIC Microcontroller

#include "p18f4550.h"
//Configuration bits setting//
#pragma config FOSC = HS //Oscillator Selection
#pragma config WDT = OFF //Disable Watchdog timer
#pragma config LVP = OFF //Disable Low Voltage Programming
#pragma config PBADEN = OFF //Disable PORTB Analog inputs
//Declarations
#define Brd_Fosc 20000000
#define 12C CLOCK 100E3
#define SSPADD_VAL ((Brd_Fosc/(412C_CLOCK))-1)
#define LCD DATA PORTD 
//LCD data port
#define en PORTEbits.RE2 // enable signal
#define rw PORTEbits.RE1 // read/write signal
#define rs PORTEbits.REO // register select signal
//Function Prototypes
void I2C_init(void); //Function to initialise I2C module
unsigned char I2C_byte_write(unsigned char device,unsigned char address,unsigned char data); unsigned char I2C_byte_read (unsigned char device,unsigned char address);
void init_LCD(void);
void LCD command(unsigned char cmd); void LCD data(unsigned char data);
void LCD write string(static char *str); void msdelay (unsigned int time);
void ascii display (unsigned char rtc data);
//Function to initialise the LCD
//Function to pass command to the LCD //Function to write character to the LCD //Function to write string to the LCD //Function to generate delay
//Function to convert BCD to ascii
//Start of Main Program
void main(void)
{
unsigned char i,j;
unsigned char val;
unsigned char msgl[ ]="SKNCOE";
unsigned char msg2[ ]="I2C RTC TEST";
unsigned char msg3[ ]="writing to RTC";
unsigned char msg4[ ]Date n Time";
HRTC_Register_MAP: //SS:MM:HH Day, Date, Month, Year
unsigned char RTC_REGH={0x50,0x59,0x71,0x02,0x21,0x08,0x14,1\01;
TRISD = Ox00; //Configuring PORTD as output
TRISE = Ox00; //Configuring PORTE as output
ADCON1=0x0F; //make ALL PORT PIN as digital
//Display Messages
LCD_write_string(msg1);
LCD_command(Oxc0);
LCD_write_string(msg2);
msdelay(500);
LCD_command(Ox01);
LCD_write_string(msg3);
LCDcommand(Oxc0);
LCD_write_string(msg4);
msdelay(500);
//Configure RTC
for (i=0;i < 7; i++)
{
I2C byte_write (OxDO,i, RTC_REG[i]);
msdelay(20);
}
LCD_command(Ox01);
LCD_command(Ox80);

RTC REG[2] = 12C_byte_read (0xD0,0x02);

val = RTCREG[2] & 0x1F; //Ignore AM/PM n 12/23 info

ascii_display (val); //Display Hours

LCD_data (':');

RTC_REG[1] = 12C_byte_read (0xD0,0x01);

ascii_display (RTC_REG[1]); //Display Minutes

LCD_data (':');

RTC_REG[0] = 12C_byte_read (0xD0,0x00);

ascii_display (RTC_REG[0]); //Display Seconds

val=RTC_REG[2]&0x20;

LCD data (");

if(val)

LCD_data ('P');

else

LCD_data ('A');

LCD_data ('M');

//Getting AM or PM from hours location



RTC_REG[4] = I2C_byte_read (0xD0,0x04);

ascii_display (RTC_REG[4]);//Display Date

RTC_REG[5] = 12C_byte_read (0xD0,0x05);

ascii_display (RTC_REG[5]); //Display Month

LCD_data ('/');

LCD_data (2');

LCD_data ('0');

RTC_REG[6] = 12C_byte_read (0xD0,0x06);

ascii_display (RTC_REG[6]);//Display Year

msdelay(250);



}

}



//Function Definitions

void 120_init()

{

TRISBbits.TRISB0=1; //Setting up SDA/SCL pins as inputs

TRISBbits.TRISB1=1;

SSPCON1 = 0x08; //12C Master mode, clock = FOSC/(4 * (SSPADD + 1))

SSPSTATbits.SMP=1; //Enabling slew control for high sped mode

SSPADD= SSPADD_VAL; //Setting I2C clock

SSPCON1bits.SSPEN=1;//Enabling MSSP module

}



unsigned char I2C_byte_write(unsigned char device,unsigned char address,unsigned char data) {

SSPCON2bits.SEN=1; //Generating start condition

while(!PIR1bits.SSPIF); //Waiting for transmission of start bit

PlRlbits.SSPIF=O; //Clearing SSPIF flag

SSPBUF=device&OxFE; //Sending Device Address

while(!PIR1bits.SSPIF); //Waiting for transmission of device address

PlRlbits.SSPIF=O; //Clearing SSPIF flag

SSPBUF=address; //Sending Memory Location

while(!PIR1bits.SSPIF); //Waiting for transmission of memory address

PlRlbits.SSPIF=O; //Clearing SSPIF flag

SSPBUF=data;

while(!PIR1bits.SSPIF);

PlRlbits.SSPIF=O;

SSPCON2bits.PEN=1; //Generating STOP condition

while(!PIR1bits.SSPIF); //Waiting for transmission of stop bit

PlRlbits.SSPIF=O; //Clearing SSPIF flag

}



unsigned char I2C_byte_read(unsigned char device,unsigned char address)

{

unsigned char data;

SSPCON2bits.SEN=1; //Generating start condition

while(!PIR1bits.SSPIF); //Waiting for transmission of start bit

PIR1bits.SSPIF=0; //Clearing SSPIF flag

SSPBUF=device&OxFE; //Selecting device in write mode



while(!PIR1bits.SSPIF);

PIRlbits.SSPIF=O;

SSPBUF=address;

while(! PI R1bits.SSPIF);

PIRlbits.SSPIF=O;



SSPCON2bits. RSEN=1; //generating repeated start condition

while(! PI R1bits.SSPIF);

PIR1bits.SSPIF=0;



////Sending Read Command

SSPBUF=devicel0x01; //Sending Address

while(!PIR1bits.SSPIF); //Waiting for transmission of read command along with reception of ACK bit

PIRlbits.SSPIF=O; //Clearing SSPIF flag

SSPCON2bits.RCEN=1; //Enabling Master Receive Mode

while(!PIR1bits.SSPIF); //Waiting to receive a byte

PlRlbits.SSPIF=O; //Clearing interrupt flag

data=SSPBUF; //Getting received data byte

SSPCON2bits.PEN=1;

while(!PIR1bits.SSPIF);

PlRlbits.SSPIF=O;

return data;

}

//Generating STOP condition

void msdelay (unsigned int time) //Function to generate delay

{

unsigned int i, j;

for (i = 0; i < time; i++)

for (j = 0; j < 275; j++);//Calibrated for a 1 ms delay in MPLAB

}

init_LCD(void) // Function to initialise the LCD

{

LCDcommand(Ox38); // initialization of 16X2 LCD in 8bit mode

msdelay(15);

LCDcommand(Ox01); // clear LCD

msdelay(15);

LCD_command(Ox0C); // cursor off

msdelay(15);

LCD_command(Ox80); // go to first line and 0th position

msdelay(15);

}

void LCD_command(unsigned char cmd) //Function to pass command to the LCD

{

LCD DATA =

rs = 0;

rw = 0;

en = 1;

msdelay(15);

en = 0;

cmd; //Send data on LCD data bus

//RS = 0 since command to LCD

//RW = 0 since writing to LCD

//Generate High to low pulse on EN

void LCD _data(unsigned char data)//Function to write data to the LCD

{

LCD_DATA = data; //Send data on LCD data bus

rs = 1; //RS = 1 since data to LCD

rw = 0; //RW = 0 since writing to LCD

en = 1; //Generate High to low pulse on EN

msdelay(15);

en = 0;

}

//Function to write string to LCD

void LCD_write_string(static char *str)

{

int i = 0;

while (str[i] != 0)

{

LCD data(str[i]);

msdelay(15);

i++;

}
// sending data on LCD byte by byte

void ascii_display (unsigned char rtc_data)
{

unsigned char temp;

ternp=rtc_data; //Store data Temporarily

temp=temp&OxFO; //unpack higher byte

temp=(temp>>4)I0x30; //Add 0x30 to unpacked BCD

LCD_data (temp); //write converted BCD digit

temp=rtc_data; //Store data Temporarily

temp=(temp&OxOF); //unpack lower byte

temp=templ0x30; //Add 0x30 to unpacked BCD

LCD_data (temp); //write converted BCD digit

}

References

  • Notes by Prof S.S.Kendre, Created and Edited by Prof. Sujit Wagh, Sinhgad's SKNCOE, Pune
  • Interfacing Diagram by Mr. Jayesh Gopal, Student, and WikiNote Volunteer
  • Open Lab Pro
  • WikiNote Foundation
Tags:
Created by Sujit Wagh on 2017/09/27 19:09