Continue to Site

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.

  • 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.

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:
 
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.

Latest threads

New Articles From Microcontroller Tips

Back
Top