Interfacing DS1307 Real time clock with PIC16f877

By | February 27, 2014

In any advance project we need real time clock synchronize with our work and for this purpose the best option is DS1307 (RTC Ic). Interfacing DS1307 Real time clock with PIC16f877 is done by I2C communication. To know I2C protocol you may refer my previous post “Interfacing external EEPROM with PIC Microcontroller”.  To know about Interfacing DS1307 Real time clock with PIC16f877, we should know something about DS1307 IC.

Real time clock ( DS1307):

The DS1307 serial real-time clock (RTC) is a low-power, full binary-coded decimal (BCD) clock/calendar plus 56 bytes of NV Interfacing DS1307 Real time clock with PIC16f877SRAM. Address and data are transferred serially through an I2C, bidirectional bus. The clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The date at the end of the month is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The DS1307 operates as a slave device on the I2C bus. Access is obtained by implementing a START condition and providing a device identification code followed by a register address. Subsequent registers can be accessed sequentially until a STOP condition is executed.

Project Description:

In this project we will see how we interfaced DS1307 with pic16f877 via I2C protocol. After interfacing DS1307 we recive the data from DS1307 and display it on LCD. Weall ready know before that DS1307 is send data in full BCD format. So we have to convert this data in digit and send to display on LCD.

Now question is how we convert BCD number to 4 bit number?

For getting higher nibble we use command

return ((bcd >> 4) + ‘0’) : it means the number will be Binary Right Shift 4 times with loading zero on left side.

For getting Lower nibble we use command

return ((bcd & 0x0F) + ‘0’) : it means we did and operation 0F with BCD number.

Now see the diagram of Interfacing DS1307 Real time clock with PIC16f877 in Proteus

Interfacing DS1307 Real time clock with PIC16f877

See the full embedded code at bellow.

Embedded C Code
// Name : Interfacing DS1307 Real time clock with PIC16f877
// Author : Subham Dutta
// Date : 27-02-14
// Website : www.nbcafe.in

unsigned short take=0;
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;

unsigned short read_ds1307(unsigned short address)
{
unsigned short r_data;
I2C1_Start();
I2C1_Wr(0xD0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 –> 0xD0
I2C1_Wr(address);
I2C1_Repeated_Start();
I2C1_Wr(0xD1); //0x68 followed by 1 –> 0xD1
r_data=I2C1_Rd(0);
I2C1_Stop();
return(r_data);
}

char time[] = “00:00:00”;
char date[] = “00-00-00″;

unsigned char BCD2UpperCh(unsigned char bcd)
{
return ((bcd >> 4) + ‘0’);
}

unsigned char BCD2LowerCh(unsigned char bcd)
{
return ((bcd & 0x0F) + ‘0’);
}

void main() {
int b,sec,mm,hh,dd,mo,yr,i=0,dela;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_out(1,1,”Time:”);
Lcd_out(2,1,”Date:”);

I2C1_Init(100000);

while(1)
{
sec = read_ds1307(0);
mm = read_ds1307(1);
hh = read_ds1307(2);
dela = read_ds1307(3);
dd = read_ds1307(4);
mo = read_ds1307(5);
yr = read_ds1307(6);

time[0] = BCD2UpperCh(hh);
time[1] = BCD2LowerCh(hh);
time[3] = BCD2UpperCh(mm);
time[4] = BCD2LowerCh(mm);
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);

date[0] = BCD2UpperCh(dd);
date[1] = BCD2LowerCh(dd);
date[3] = BCD2UpperCh(mo);
date[4] = BCD2LowerCh(mo);
date[6] = BCD2UpperCh(yr);
date[7] = BCD2LowerCh(yr);
Lcd_out(1, 6, time);
Lcd_out(2, 6, date);
Delay_ms(1000);

}

}

2 thoughts on “Interfacing DS1307 Real time clock with PIC16f877

  1. Sid Tryzbiak

    Hi,

    I modified several things to try to get this to work on my MikroElektronika Fusion v7 development 32 bit board. I changed LCD info to work on my LCD and PIC32mx795f512L. Changed command to make all AN signals digital and added CHECON = 0x32; // Prefetch cache pic32mx. Changed to SCL2, SDA2.

    Still does not put time and date on LCD. It does print those words though. Any ideas?

    Thanks,

    Sid

    // Name : Interfacing DS1307 Real time clock with PIC16f877
    // Author : Subham Dutta
    // Date : 27-02-14
    // Website : http://www.nbcafe.in

    unsigned short take=0;
    // LCD module connection EasyPic Fusion V7 PIC32MX795F512L
    sbit LCD_RS at LATD9_bit;
    sbit LCD_EN at LATD10_bit;
    sbit LCD_D4 at LATE4_bit;
    sbit LCD_D5 at LATE5_bit;
    sbit LCD_D6 at LATE6_bit;
    sbit LCD_D7 at LATE7_bit;

    sbit LCD_RS_Direction at TRISD9_bit;
    sbit LCD_EN_Direction at TRISD10_bit;
    sbit LCD_D4_Direction at TRISE4_bit;
    sbit LCD_D5_Direction at TRISE5_bit;
    sbit LCD_D6_Direction at TRISE6_bit;
    sbit LCD_D7_Direction at TRISE7_bit;
    // End LCD module connections

    int b,sec,mm,hh,dd,mo,yr,i=0,dela;
    char time[] = “00:00:00”;
    char date[] = “00-00-00″;

    unsigned short read_ds1307(unsigned short address)
    {
    unsigned short r_data;
    I2C2_Start();
    I2C2_Write(0xD0); //address 0×68 followed by direction bit (0 for write, 1 for read) 0×68 followed by 0 –> 0xD0
    I2C2_Write(address);
    I2C2_Restart();
    I2C2_Write(0xD1); //0×68 followed by 1 –> 0xD1
    r_data=I2C2_Read(0);
    I2C2_Stop();
    return(r_data);
    }

    unsigned char BCD2UpperCh(unsigned char bcd)
    {
    return ((bcd >> 4) + ‘0’);
    }

    unsigned char BCD2LowerCh(unsigned char bcd)
    {
    return ((bcd & 0x0F) + ‘0’);
    }

    void main() {
    CHECON = 0x32; // Prefetch cache pic32mx
    AD1PCFG = 0xFFFF; // Configure AN pins as digital I/O pic32mx

    Lcd_Init(); // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR); // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
    Lcd_out(1,1,”Time:”);
    Lcd_out(2,1,”Date:”);

    I2C2_Init(100000);

    while(1)
    {
    sec = read_ds1307(0);
    mm = read_ds1307(1);
    hh = read_ds1307(2);
    dela = read_ds1307(3);
    dd = read_ds1307(4);
    mo = read_ds1307(5);
    yr = read_ds1307(6);

    time[0] = BCD2UpperCh(hh);
    time[1] = BCD2LowerCh(hh);
    time[3] = BCD2UpperCh(mm);
    time[4] = BCD2LowerCh(mm);
    time[6] = BCD2UpperCh(sec);
    time[7] = BCD2LowerCh(sec);

    date[0] = BCD2UpperCh(dd);
    date[1] = BCD2LowerCh(dd);
    date[3] = BCD2UpperCh(mo);
    date[4] = BCD2LowerCh(mo);
    date[6] = BCD2UpperCh(yr);
    date[7] = BCD2LowerCh(yr);
    Lcd_out(1, 6, time);
    Lcd_out(2, 6, date);
    Delay_ms(1000);

    }

    }

    Reply
  2. pratheep

    how to set time to ds1307,i.e,how does it set automatically,then how does ds1307 knows that now the time is something like 12:30 pm

    Reply



Leave a Reply

Your email address will not be published. Required fields are marked *