INTERFACING DS1307 RTC WITH PIC16F887 VIA I2C.

Find out how to setup your programmer's software and how to solve many common problems.

Moderator: phalanx

Post Reply
naveenjo
Posts: 2
Joined: Sat Dec 13, 2014 10:49 am

INTERFACING DS1307 RTC WITH PIC16F887 VIA I2C.

Post by naveenjo » Wed Dec 28, 2016 8:19 am

friends,
I am trying to interface DS1307 RTC with pic16f887 controller via i2c.. while simulation i got the time and date.. but the problem is I have to write this time to my LCD... in this program I am trying to write the "hour" value to LCD..
but nothing visible in LCD... please help me..please checkout the attachment and MPLABx code too...
PIC clock= 20Mhz
I²C clock= 100Khz
DS1307 address= 1101000

I AM NOT SURE THAT THE CODES I WRITTEN INSIDE FUNCTION -->ds1307_read() is right or wrong...please help

Actually in code I am trying to display the value of "hour" in LCD.. using functions bcd2lowerch and bcd2upperch
when I tried to debug my code in proteus::--->>>
1). when I debugged the function call-> hour=ds1307_read(0x02), inside the function, returning value of x is equal to 2. which means the address-> 0x02 which is passing as the parameter in function hour=ds1307_read(0x02), is stored inside SSPBUF and returning as such... which means a right read from the hour register of ds1307, is not taking place...
2).Similarly, when I debugged the function call-> minutes = ds1307_read(0x01);inside the function, returning value of x is equal to 1. which means the address-> 0x01 which is passing as the parameter in function minutes = ds1307_read(0x01), is stored inside SSPBUF and returning as such... which means a right read from the minute register of ds1307, is not taking place...
3).Similarly, when I debugged the function call-> seconds = ds1307_read(0x00);inside the function, returning value of x is equal to 0. which means the address-> 0x00 which is passing as the parameter in function seconds = ds1307_read(0x00), is stored inside SSPBUF and returning as such... which means a right read from the second register of ds1307, is not taking place...

________________________MPLAB CODE______________________________________

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include<htc.h>
#define _XTAL_FREQ 20000000 //20Mhz
#define RS RC5
#define RW RC6
#define E RC7

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_ON & IESO_ON & FCMEN_ON & LVP_OFF);
__CONFIG(BOR4V_BOR40V & WRT_OFF);
void init_i2c(void);
void ds1307_init(void);
void ds1307_write(unsigned char ,unsigned char);
unsigned short ds1307_read(unsigned short);
void wait_mssp(void);
void init_lcd();
void set_command(unsigned char);
void set_data(unsigned char *);

unsigned short seconds,minutes,hour;
unsigned short x;
unsigned char hourVal[5]={0};
unsigned char hourVal1[5]={0};
unsigned short a;
unsigned short b;
unsigned char bcd2upperch(unsigned char bcd);
unsigned char bcd2lowerch(unsigned char bcd);


void main(){
    
    PORTD =0x00;
    TRISD =0x00;
    TRISC5 =0;
    TRISC6 =0;
    TRISC7 = 0;
    init_lcd();
    __delay_ms(100);
    init_i2c();
    __delay_ms(100);
    
    
    while(1){
        
       seconds = ds1307_read(0x00);
       minutes = ds1307_read(0x01);
       hour = ds1307_read(0x02);
       
       a = bcd2lowerch(hour);
       b = bcd2upperch(hour);
       
       sprintf(hourVal,"hour=%d",b); //sprintf used to get output as string
       sprintf(hourVal1,"%d",a);
       set_command(0x80); //force cursor to begin in 1st line of LCD
       set_data(hourVal);
       set_data(hourVal1);
       __delay_ms(1000);
         
    }
}
unsigned char bcd2upperch(unsigned char bcd)
{
 return((bcd >> 4) + '0');
}

unsigned char bcd2lowerch(unsigned char bcd)
{
 return((bcd & 0x0f) + '0');
}

void init_i2c(void){
    SSPSTAT=0x00;
    SSPCON=0x00;
    SSPCON2=0x00; 
    SSPADD=0x00; 
    PORTC=0x00;
    TRISC3 =1;
    TRISC4 =1;
    SSPCON = 0b00101000;//0x28 i2c master mode
    SSPADD = 0x31;//decimal--49.//value for SSPADD found using eqn--> clock =Fosc/ 4*(SSPADD +1); clock--100Khz, Fosc =20Mhz
    SSPSTAT = 0b10000000; //0x80
    TRISC3 =1;
    TRISC4 =1;
    ds1307_write(0,0x00);
    
}
unsigned short ds1307_read(unsigned short addr){
  
 RCEN =1;
 wait_mssp();
 SSPBUF =0b11010000; //slave address(address of ds1307) + write bit;
 wait_mssp();
 SSPBUF =addr;
 wait_mssp();
 RSEN =1;
 SSPBUF =0b11010001; //slave address(address of ds1307) + read bit;
 wait_mssp();
 ACKDT=1;
 ACKEN =1;
 PEN=1;
 wait_mssp();
 x = SSPBUF;
 return x;
}
void ds1307_write(unsigned char addr ,unsigned char data){
    
    SEN =1; //Start bit
    wait_mssp();
    SSPBUF = 0b11010000; //slave address(address of ds1307) + write bit
    wait_mssp();
    SSPBUF =addr;
    wait_mssp();
    SSPBUF = data; 
    wait_mssp();
    PEN =1; //stop bit
    wait_mssp(); 
     
}
void wait_mssp(void){
    while(!SSPIF);
    SSPIF =0;
   }

void init_lcd(){
    
set_command(0x01); //display clear 
set_command(0x38); //Function set -- 8bit data and 2lines 
set_command(0x0C); //display ON cursor ON BLINK off 
set_command(0x06); //Increment cursor--shift display to RIGHT
set_command(0x0E); //DISPLAY ON CURSOR BLINK
set_command(0x80); //force cursor to begin in 1st line
}


void set_command(unsigned char command){
    RS = 0; //command
    RW = 0; //write
    PORTD=command;
    E =1;
    __delay_ms(100);
    E =0;
  }

void set_data(unsigned char *a){
    RS = 1; //data
    RW =0; // write
    while(*a)
    {
    PORTD = *a;
        E =1;
    __delay_ms(100);
    E =0;
    a++;
    }
}
Attachments
i2c_newww.jpg
debug.jpg
please find the attachments too

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: INTERFACING DS1307 RTC WITH PIC16F887 VIA I2C.

Post by phalanx » Wed Dec 28, 2016 9:13 am

Hi Naveenjo,

Take a look at page 13 of the DS1307 datasheet from Maxim. It details the sequence you need to coordinate to write the data pointer and then immediately start receiving data from the RTC. Relate this to page 85 of the PIC's datasheet to see a timing diagram of how a reception works.

In your read function, you are immediately setting the RCEN bit which is starting a reception before you have initialized the I2C bus. Your read sequence, including a data pointer update, should look something like this:

Send Start condition
Transmit address to slave as a write command
Check for ACK from slave
Send data pointer address
Check for ACK from slave
Send Repeated Start condition
Transmit address to slave as a read command
Check for ACK from slave
Set receive enable on PIC
Generate ACK after byte is received
(repeat the previous 2 steps for every byte you want to receive)
Send Stop condition

You will obviously have to manage the timing between all these steps whether by monitoring specific bits in the control registers for through the MSSP interrupt flag. This should get you moving in the right direction.

-Bill

jremington
Support Volunteer
Posts: 2102
Joined: Fri Jun 15, 2007 9:41 pm
Location: Eugene, Or

Re: INTERFACING DS1307 RTC WITH PIC16F887 VIA I2C.

Post by jremington » Wed Dec 28, 2016 9:46 am

Take a look at the offerings from the CCSC forum. You should be able to modify them appropriately for whatever compiler and I2C routines you are using.

https://www.ccsinfo.com/forum/viewtopic.php?t=23255

Post Reply