Please help to write the function for DS1307 in my code

Status
Not open for further replies.

jab99407

Member
I am trying to write code for DS1307. I just want to write the first five registers of DS1307

Here is code
C:
#include <xc.h>

// Configuration word for PIC16F877A
__CONFIG( FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

#define _XTAL_FREQ    20000000


// Define i2c pins
#define SDA         RC4           // Data pin for i2c
#define SCK         RC3           // Clock pin for i2c
#define SDA_DIR     TRISC4        // Data pin direction
#define SCK_DIR     TRISC3        // Clock pin direction
#define I2C_SPEED   100            // kbps

#define Address     0xD0 
#define WordAddress 0x00

// Function Purpose: Configure I2C module
void InitI2C(void)
{
    SDA_DIR = 1;    // Make SDA and
    SCK_DIR = 1;    // SCK pins input
    SSPADD  = ((_XTAL_FREQ/4000)/I2C_SPEED) - 1;
    SSPSTAT = 0x80;    // Slew Rate control is disabled
    SSPCON  = 0x28;    // Select and enable I2C in master mode
}

// Function Purpose: I2C_Start sends start bit sequence
void I2C_Start(void)
{
    SEN = 1;      // Send start bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}

//Function : I2C_Stop sends stop bit sequence
void I2C_Stop(void)
{
    PEN = 1;      // Send stop bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}
// Function Purpose: I2C_Write_Byte transfers one byte
__bit I2C_Write_Byte(unsigned char Byte)
{
    SSPBUF = Byte;    // Send Byte value
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
    return ACKSTAT;    // Return ACK/NACK from slave
}

void Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size)
{
    I2C_Start();                    // Start i2c communication
    I2C_Write_Byte(address);        // Send i2c address of DS1307 with write command
    I2C_Stop();                      // Stop i2c communication
}

void main(void)
{
    unsigned char Size = 6;
    unsigned char DataByte[ ] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    InitI2C();
    Write_Byte_To_DS1307_RTC( Address, WordAddress, DataByte, Size); 
}

I am stuck with the following function. When I send the device address. After that, I need to check ACK/NAK . after that I am thinking to use a loop to send value in five registers

C:
void Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size)

{

    I2C_Start();                    // Start i2c communication

    I2C_Write_Byte(address);        // Send i2c address of DS1307 with write command

    I2C_Stop();                      // Stop i2c communication

}
 
Last edited:
You don't use the stop function until the transaction is complete.

See the examples at post #15 in this thread:
 
How to write code for the following statement
  • Master first sends a START condition to the bus
  • Master sends a slave address to the bus
  • Wait for ACK / NAK
  • if slave is acknowledged then send the next byte
  • if not acknowledged then stop
  • check ACK / NAK after sending each byte
I wrote the first two points having difficulty for others points

C:
void Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size)

{

    I2C_Start();                    // Start i2c communication

    I2C_Write_Byte(address);        // Send i2c address of DS1307 with write command

  

}
 
Master sends a slave address to the bus
Wait for ACK / NAK

Not to be too picky here, but you don't "wait" for ACK/NAK... it comes during the 9th clock after writing the byte.
You check the return value from I2C_Write_Byte() function, which is the ACKSTAT bit.
 
Does it make any sense for you ?

C:
void Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size)

{

    I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
    }

    if (I2C_Write_Byte(wordAddress) == 1)    //Send i2c address of DS1307 with write command
    {
        I2C_Stop();
    }
   
    while ( size > 0)                         // assume size is 6
    {
        if (I2C_Write_Byte(*DataByte) == 1)
        {
           I2C_Stop();
        }
           
        DataByte)++;      
        size--;
    }
   I2C_Stop();
}
 
Last edited:
No, when you get a NACK to the address byte you should send STOP and exit.
You'll have to repeat the entire sequence from the beginning
Code:
void Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size)

{

    I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
// must exit here... return a failure code so the caller knows to repeat the call

    }
 
No, when you get a NACK to the address byte you should send STOP and exit.
You'll have to repeat the entire sequence from the beginning
corrected code

C:
#include <xc.h>

// Configuration word for PIC16F877A
__CONFIG( FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

#define _XTAL_FREQ    20000000


// Define i2c pins
#define SDA         RC4           // Data pin for i2c
#define SCK         RC3           // Clock pin for i2c
#define SDA_DIR     TRISC4        // Data pin direction
#define SCK_DIR     TRISC3        // Clock pin direction
#define I2C_SPEED   100            // kbps

#define Address     0xD0
#define WordAddress 0x00

// Function Purpose: Configure I2C module
void InitI2C(void)
{
    SDA_DIR = 1;    // Make SDA and
    SCK_DIR = 1;    // SCK pins input
    SSPADD  = ((_XTAL_FREQ/4000)/I2C_SPEED) - 1;
    SSPSTAT = 0x80;    // Slew Rate control is disabled
    SSPCON  = 0x28;    // Select and enable I2C in master mode
}

// Function Purpose: I2C_Start sends start bit sequence
void I2C_Start(void)
{
    SEN = 1;      // Send start bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}

//Function : I2C_Stop sends stop bit sequence
void I2C_Stop(void)
{
    PEN = 1;      // Send stop bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}
// Function Purpose: I2C_Write_Byte transfers one byte
__bit I2C_Write_Byte(unsigned char Byte)
{
    SSPBUF = Byte;    // Send Byte value
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
    return ACKSTAT;    // Return ACK/NACK from slave
}

// Function Purpose: I2C_Read_Byte reads one byte
unsigned char I2C_Read_Byte(void)
{
    RCEN = 1;      // Enable reception of 8 bits
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit

    return SSPBUF;    // Return received byte
}

unsigned char Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size )

{

     I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 1;
    }

    if (I2C_Write_Byte(wordAddress) == 1)    //Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 2;
    }
  
    while ( size > 0)                        
    {
        if (I2C_Write_Byte(*DataByte) == 1)
        {
           I2C_Stop();
           return 3;
        }
          
        DataByte++;     
        size--;
    }
    return 0;
}

void main(void)
{
    unsigned char TransferResult;
    unsigned char Size = 6;
    unsigned char DataByte[ ] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
  
    InitI2C();
  
    TransferResult = Write_Byte_To_DS1307_RTC( Address, WordAddress, DataByte, Size);
}
 
Last edited:
I have added function to read DS1307 registers but I am stuck in function
C:
#include <xc.h>

// Configuration word for PIC16F877A
__CONFIG( FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

#define _XTAL_FREQ    20000000


// Define i2c pins
#define SDA         RC4           // Data pin for i2c
#define SCK         RC3           // Clock pin for i2c
#define SDA_DIR     TRISC4        // Data pin direction
#define SCK_DIR     TRISC3        // Clock pin direction
#define I2C_SPEED   100            // kbps

#define Address     0xD0
#define WordAddress 0x00

  unsigned char Byte[6];

// Function Purpose: Configure I2C module
void InitI2C(void)
{
    SDA_DIR = 1;    // Make SDA and
    SCK_DIR = 1;    // SCK pins input
    SSPADD  = ((_XTAL_FREQ/4000)/I2C_SPEED) - 1;
    SSPSTAT = 0x80;    // Slew Rate control is disabled
    SSPCON  = 0x28;    // Select and enable I2C in master mode
}

// Function Purpose: I2C_Start sends start bit sequence
void I2C_Start(void)
{
    SEN = 1;      // Send start bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}

//Function : I2C_Stop sends stop bit sequence
void I2C_Stop(void)
{
    PEN = 1;      // Send stop bit
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}
// Function Purpose: I2C_Write_Byte transfers one byte
__bit I2C_Write_Byte(unsigned char Byte)
{
    SSPBUF = Byte;    // Send Byte value
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
    return ACKSTAT;    // Return ACK/NACK from slave
}

// Function Purpose: I2C_Read_Byte reads one byte
unsigned char I2C_Read_Byte(void)
{
    RCEN = 1;      // Enable reception of 8 bits
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit

    return SSPBUF;    // Return received byte
}

//Function : I2C_Send_ACK sends ACK bit sequence
void I2C_Send_ACK(void)
{
    ACKDT = 0;      // 0 means ACK
    ACKEN = 1;      // Send ACKDT value
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}
//Function : I2C_Send_NACK sends NACK bit sequence
void I2C_Send_NACK(void)
{
    ACKDT = 1;      // 1 means NACK
    ACKEN = 1;      // Send ACKDT value
    while(!SSPIF);    // Wait for it to complete
    SSPIF = 0;      // Clear the flag bit
}

unsigned char Write_Byte_To_DS1307_RTC(unsigned char address, unsigned char wordAddress, unsigned char *DataByte, unsigned char size )
{
     I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 1;
    }

    if (I2C_Write_Byte(wordAddress) == 1)    //Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 2;
    }
 
    while ( size > 0)                       
    {
        if (I2C_Write_Byte(*DataByte) == 1)
        {
           I2C_Stop();
           return 3;
        }
          
        DataByte++;     
        size--;
    }
    return 0;
}

unsigned char Read_Byte_From_DS1307_RTC( unsigned char address, unsigned char wordAddress, unsigned char *byte, unsigned char Size)
{
     I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 1;
    }
    Byte[0] = I2C_Read_Byte(*byte);
    I2C_Send_ACK();
    *byte++;
    Byte[1] = I2C_Read_Byte(*byte);
    I2C_Send_ACK();
    *byte++;
     Byte[2] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
     Byte[3] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
     Byte[4] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
    Byte[5] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    I2C_Send_NACK();
    I2C_Stop();
    
    return 2;
}

void main(void)
{
    unsigned char TransferResult;
    unsigned char ReceiveResult;
    unsigned char Size = 6;
    unsigned char DataByte[ ] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
 
    InitI2C();
 
    TransferResult = Write_Byte_To_DS1307_RTC( Address, WordAddress, DataByte, Size);
    ReceiveResult = Read_Byte_From_DS1307_RTC( 0xD1, WordAddress,  Byte, Size);
}

I want to use a loop to read each byte. Is my sequence correct in function?

C:
unsigned char Read_Byte_From_DS1307_RTC( unsigned char address, unsigned char wordAddress, unsigned char *byte, unsigned char Size)
{
     I2C_Start();                              // Start i2c communication

    if (I2C_Write_Byte(address) == 1)        // Send i2c address of DS1307 with write command
    {
        I2C_Stop();
        return 1;
    }
    Byte[0] = I2C_Read_Byte(*byte);
    I2C_Send_ACK();
    *byte++;
    Byte[1] = I2C_Read_Byte(*byte);
    I2C_Send_ACK();
    *byte++;
     Byte[2] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
     Byte[3] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
     Byte[4] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    *byte++;
    Byte[5] = I2C_Read_Byte(byte);
    I2C_Send_ACK();
    I2C_Send_NACK();
    I2C_Stop();
    
    return 2;
}
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…