• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

I2C DS1307 problem

Status
Not open for further replies.

johnl69

Member
Im trying to read from a DS1307 using a 18f8720 pic and display on LCD

Im using a routine that ive used on an 18f4550 which I had working but since transfering to a different pic it no longer updates the time.
Im incline to beleive its got some thing to do with the baud rate as the timings dont look right when I simulate it in Proteus.

using MplabX and xc8 compiler.

main routine;
C:
/* 
 * File:   Controller_Main.c
 * Author: john
 *
 * Created on October 26, 2016, 9:48 AM
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "lcd.h"
#include "i2c.h"

#define _XTAL_FREQ 4000000

#define MSB(x) ((x>>4)+ '0')            //Display Most Significant Bit of BCD number
#define LSB(x) ((x & 0x0F) + '0')       //Display Least Significant Bit of BCD number

#define I2C_SCL    TRISCbits.TRISC3
#define I2C_SDA    TRISCbits.TRISC4

unsigned short read_ds1307(unsigned short addressReg); //Function to read from the DS1307
void write_ds1307(unsigned short addressReg, unsigned short w_dataReg); //Function to write to the DS1307
int Binary2BCD(int aa); //Convert Binary to BCD
int BCD2Binary(int aa); //Convert BCD to Binary
char time[] = "00:00:00";
int second;
int minute;
int hour;
int hr;
unsigned short set_count = 0;
short set;
int absolute(int a);
void DelayFor18TCY(void);
void DelayPORXLCD(void);
void DelayXLCD(void);

void main(void) {

    ADCON1 = 0xF; // No analog, all digital i/o
    TRISA = 0xCF;
    TRISB = 0x0;
    TRISC = 0x0;
    TRISG = 0x00;
    LATB = 0x00;
    LATG = 0x00;

    while (1) {
       
        while (BusyXLCD());
        OpenXLCD(FOUR_BIT & LINES_5X7);
        while (BusyXLCD());
        WriteCmdXLCD(CURSOR_OFF & BLINK_OFF);
        while (BusyXLCD());
        WriteCmdXLCD(SHIFT_DISP_LEFT);
           
        OpenI2C(MASTER, SLEW_OFF); // Initialize I2C module
        SSPADD = 9;    //Baud clock 
                        //SSPADD = (FOSC/ Bit Rate) /4 - 1
        IdleI2C();
        StartI2C();
        while (SSPCON2bits.SEN);

        for (;;) {
           
            putrsXLCD("Time:");
            SetDDRamAddr(0x40);
           
            do{

            //Read Time 
            hour = read_ds1307(0x02); //Read Hour
            minute = read_ds1307(0x01); //Read minutes
            second = read_ds1307(0x00); //Read seconds

            time[0] = MSB(hour);
            time[1] = LSB(hour);
            time[3] = MSB(minute);
            time[4] = LSB(minute);
            time[6] = MSB(second);
            time[7] = LSB(second);



            SetDDRamAddr(0x06);
            putrsXLCD(time);
            }while(1);

        }
    }
}

// LCD Delay Routines

void DelayFor18TCY(void) {
    __delay_us(18);

}

void DelayPORXLCD(void) {
    __delay_ms(15);

}

void DelayXLCD(void) {
    __delay_ms(5);

}
// abs.c routine conflicting in xc8

int
absolute(int a) {
    if (a < 0)
        return -a;
    return a;
}

unsigned short read_ds1307(unsigned short address) //call this function to read date and time
//from the date and time registers.
{
    char r_data;
    StartI2C(); // Start condition I2C on bus
    IdleI2C();
    WriteI2C(0xD0); // addresses the chip
    IdleI2C();
    WriteI2C(address); // write register address
    IdleI2C();
    StopI2C(); // Stop condition I2C on bus

    RestartI2C(); // Start condition I2C on bus
    IdleI2C();
    WriteI2C(0xD1); // addresses the chip with a read bit
    IdleI2C();
    r_data = ReadI2C(); // read the value from the RTC and store in result
    IdleI2C();
    NotAckI2C(); // Not Acknowledge condition.
    IdleI2C();
    StopI2C(); // Stop condition I2C on bus
    return (r_data);
}

void write_ds1307(unsigned short address, unsigned short w_data) //call this function to write date and time
//to the date and time registers.
{
    StartI2C(); // Start condition I2C on bus
    IdleI2C();
    WriteI2C(0xD0); // addresses the chip
    IdleI2C();
    WriteI2C(address); // write register address
    IdleI2C();
    WriteI2C(w_data); // write register address
    IdleI2C();
    StopI2C(); // Stop condition I2C on bus

}

int Binary2BCD(int a) //Convert Binary to BCD so we can write to the DS1307 Register in BCD
{
    int t1, t2;
    t1 = a % 10;
    t1 = t1 & 0x0F;
    a = a / 10;
    t2 = a % 10;
    t2 = 0x0F & t2;
    t2 = t2 << 4;
    t2 = 0xF0 & t2;
    t1 = t1 | t2;
    return t1;
}

int BCD2Binary(int a) //Convert BCD to Binary so we can do some basic calculations
{
    int r, t;
    t = a & 0x0F;
    r = t;
    a = 0xF0 & a;
    t = a >> 4;
    t = 0x0F & t;
    r = t * 10 + r;
    return r;
}
Pic Configuration;
C:
// PIC18F8720 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1H
#pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
#pragma config OSCS = OFF       // Oscillator System Clock Switch Enable bit (Oscillator system clock switch option is disabled (main oscillator is source))

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bit (Brown-out Reset enabled)
#pragma config BORV = 25        // Brown-out Reset Voltage bits (VBOR set to 2.5V)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 128      // Watchdog Timer Postscale Select bits (1:128)

// CONFIG3L
#pragma config MODE = MC        // Processor Mode Select bits (Microcontroller mode)
#pragma config WAIT = OFF       // External Bus Data Wait Enable bit (Wait selections unavailable for table reads and table writes)

// CONFIG3H
#pragma config CCP2MUX = ON     // CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)

// CONFIG4L
#pragma config STVR = ON        // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Low-Voltage ICSP Enable bit (Low-voltage ICSP disabled)

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000200-003FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (00C000-00FFFFh) not code-protected)
#pragma config CP4 = OFF        // Code Protection bit (Block 4 (010000-013FFFh) not code-protected)
#pragma config CP5 = OFF        // Code Protection bit (Block 5 (014000-017FFFh) not code-protected)
#pragma config CP6 = OFF        // Code Protection bit (Block 6 (018000-01BFFFh) not code-protected)
#pragma config CP7 = OFF        // Code Protection bit (Block 7 (01C000-01FFFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000200-003FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (00C000-00FFFFh) not write-protected)
#pragma config WRT4 = OFF       // Write Protection bit (Block 4 (010000-013FFFh) not write-protected)
#pragma config WRT5 = OFF       // Write Protection bit (Block 5 (014000-017FFFh) not write-protected)
#pragma config WRT6 = OFF       // Write Protection bit (Block 6 (018000-01BFFFh) not write-protected)
#pragma config WRT7 = OFF       // Write Protection bit (Block 7 (01C000-01FFFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000200-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR4 = OFF      // Table Read Protection bit (Block 4 (010000-013FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR5 = OFF      // Table Read Protection bit (Block 5 (014000-017FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR6 = OFF      // Table Read Protection bit (Block 6 (018000-01BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR7 = OFF      // Table Read Protection bit (Block 7 (01C000-01FFFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
I2C functions;
C:
#include <xc.h>
#include "i2c.h"


/**********************************************************************************************
Function Prototype : void IdleI2C(void) 

Include            : i2c.h 

Description        : This function generates Wait condition until I2C bus is Idle. 

Arguments          : None 

Return Value       : None 

Remarks            : This function will be in a wait state until Start Condition Enable bit,
                     Stop Condition Enable bit, Receive Enable bit, Acknowledge Sequence
                     Enable bit of I2C Control register and Transmit Status bit I2C Status
                     register are clear. The IdleI2C function is required since the hardware
                     I2C peripheral does not allow for spooling of bus sequence. The I2C
                     peripheral must be in Idle state before an I2C operation can be initiated
                     or write collision will be generated.
***********************************************************************************************/
void IdleI2C( void )
{
  while ( ( SSPCON2 & 0x1F ) || ( SSPSTATbits.R_W ) )
     continue;
}


/********************************************************************
*     Function Name:    NotAckI2C                                   *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      Initiate NOT ACK bus condition.             *
********************************************************************/

#undef NotAckI2C
void NotAckI2C( void )
{
  SSPCON2bits.ACKDT = 1;          // set acknowledge bit for not ACK
  SSPCON2bits.ACKEN = 1;          // initiate bus acknowledge sequence
}



/********************************************************************
*   Function Name:  OpenI2C                                         *
*   Return Value:   void                                            *
*   Parameters:     SSP peripheral setup bytes                      *
*   Description:    This function sets up the SSP module on a       * 
*                   PIC18CXXX device for use with a Microchip I2C   *
*                   EEPROM device or I2C bus device.                *
********************************************************************/

void OpenI2C( unsigned char sync_mode, unsigned char slew )
{
  SSPSTAT &= 0x3F;                // power on state 
  SSPCON1 = 0x00;                 // power on state
  SSPCON2 = 0x00;                 // power on state
  SSPCON1 |= sync_mode;           // select serial mode 
  SSPSTAT |= slew;                // slew rate on/off 

  I2C_SCL = 1;
  I2C_SDA = 1;
  SSPCON1 |= SSPENB;              // enable synchronous serial port 

}

/********************************************************************
*     Function Name:    putsI2C                                     *
*     Return Value:     error condition status                      *
*     Parameters:       address of write string storage location    *
*     Description:      This routine writes a string to the I2C bus,*
*                       until a null character is reached. If Master*
*                       function putcI2C is called. When trans-     *
*                       mission is complete then test for ack-      *
*                       nowledge bit. If Slave transmitter wait for *
*                       null character or not ACK received from bus *
*                       device.                                     *
********************************************************************/


signed char putsI2C( unsigned char *wrptr )
{
     unsigned char temp;
  while ( *wrptr )                // transmit data until null character 
  {
    if ( SSPCON1bits.SSPM3 )      // if Master transmitter then execute the following
    {
     temp = putcI2C ( *wrptr );
     if (temp ) return ( temp );            // return with write collision error
   
//      if ( putcI2C ( *wrptr ) )   // write 1 byte
//      {
//        return ( -3 );            // return with write collision error
//      }
//      IdleI2C();                  // test for idle condition
//      if ( SSPCON2bits.ACKSTAT )  // test received ack bit state
//      {
//        return ( -2 );            // bus device responded with  NOT ACK
//      }                           // terminate putsI2C() function
    }

    else                          // else Slave transmitter
    {
      PIR1bits.SSPIF = 0;         // reset SSPIF bit
      SSPBUF = *wrptr;            // load SSPBUF with new data
      SSPCON1bits.CKP = 1;        // release clock line 
      while ( !PIR1bits.SSPIF );  // wait until ninth clock pulse received

      if ( ( SSPCON1bits.CKP ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
      {
        return ( -2 );            // terminate PutsI2C() function
      }
    }

  wrptr ++;                       // increment pointer

  }                               // continue data writes until null character

  return ( 0 );
}

/********************************************************************
*     Function Name:    ReadI2C                                     *
*     Return Value:     contents of SSPBUF register                 *
*     Parameters:       void                                        *
*     Description:      Read single byte from I2C bus.              *
********************************************************************/

unsigned char ReadI2C( void )
{
if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) )    //master mode only
  SSPCON2bits.RCEN = 1;           // enable master for 1 byte reception
  while ( !SSPSTATbits.BF );      // wait until byte received  
  return ( SSPBUF );              // return with read byte 
}

/********************************************************************
*     Function Name:    RestartI2C                                  *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      Send I2C bus restart condition.             *
********************************************************************/

#undef RestartI2C
void RestartI2C( void )
{
  SSPCON2bits.RSEN = 1;           // initiate bus restart condition
}

/********************************************************************
*     Function Name:    StopI2C                                     *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      Send I2C bus stop condition.                *
********************************************************************/

#undef StopI2C
void StopI2C( void )
{
  SSPCON2bits.PEN = 1;            // initiate bus stop condition
}

/********************************************************************
*     Function Name:    StartI2C                                    *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      Send I2C bus start condition.               *
********************************************************************/

#undef StartI2C
void StartI2C( void )
{
  SSPCON2bits.SEN = 1;            // initiate bus start condition
}

/********************************************************************
*     Function Name:    WriteI2C                                    *
*     Return Value:     Status byte for WCOL detection.             *
*     Parameters:       Single data byte for I2C bus.               *
*     Description:      This routine writes a single byte to the    * 
*                       I2C bus.                                    *
********************************************************************/

signed char WriteI2C( unsigned char data_out )
{
  SSPBUF = data_out;           // write single byte to SSPBUF
  if ( SSPCON1bits.WCOL )      // test if write collision occurred
   return ( -1 );              // if WCOL bit is set return negative #
  else
  {
    if( ((SSPCON1&0x0F)!=0x08) && ((SSPCON1&0x0F)!=0x0B) )    //Slave mode only
    {
         SSPCON1bits.CKP = 1;        // release clock line 
         while ( !PIR1bits.SSPIF );  // wait until ninth clock pulse received

         if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
         {
           return ( -2 );           //return NACK
         }
         else
         {
            return ( 0 );                //return ACK
         }   
    }
    else if( ((SSPCON1&0x0F)==0x08) || ((SSPCON1&0x0F)==0x0B) )    //master mode only
    { 
       while( SSPSTATbits.BF );   // wait until write cycle is complete  
       IdleI2C();                 // ensure module is idle
       if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
          return ( -2 );            // return NACK
        else return ( 0 );              //return ACK
    }
   
  }
}

/********************************************************************
*     Function Name:    AckI2C                                      *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      Initiate ACK bus condition.                 *
********************************************************************/

#undef AckI2C
void AckI2C( void )
{
  SSPCON2bits.ACKDT = 0;           // set acknowledge bit state for ACK
  SSPCON2bits.ACKEN = 1;           // initiate bus acknowledge sequence
}

/*********************************************************************
Function Prototype : void CloseI2C(void)

Include            : i2c.h 

Description        : This function turns off the I2C module 

Arguments          : None 

Return Value       : None 

Remarks            : This function disables the I2C module and clears the
            I2C Interrupt Enable and Flag bits.
*********************************************************************/
void CloseI2C( void )
{
  SSPCON1 &= 0xDF;                // disable synchronous serial port
}

/********************************************************************
*     Function Name:    DataRdyI2C                                  *
*     Return Value:     status byte to indicate if BF = 1           *
*     Parameters:       void                                        *
*     Description:      Determine if there is a byte to be read     *
*                       from the SSPBUF register.                   *
********************************************************************/

#undef DataRdyI2C
unsigned char DataRdyI2C( void )
{
  if ( SSPSTATbits.BF )           // test if buffer full bit is set    
    return ( +1 );                // data in SSPBUF register
  else
    return ( 0 );                 // no data in SSPBUF register
}
 
Status
Not open for further replies.

EE World Online Articles

Loading
Top