DS1307 Read error I2C by bit banging.

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
594
1. I have written below code, have to just read the times from RTC. So I read all registers starting from 0x00.I always zero from RTC DS1307.
2. Time is set by Arduino board separately and I can read back by arduino correctly. So no error seems in RTC board.
But now I have to implement in another MCU with bit banging only.
3. Have checked all pull up values ok and pin scl and scd getting high and low for output_low or output_high.

Code:
#define ACK           0x00
#define NACK          0x80
#define RTC_WR        0xD0                   // WRITE instruction
#define RTC_RD        0xD1                   // READ instruction


void rtc_init(void)
{
    scl_high();
    sda_high();
    sda_output();
    scl_output();
    
}


void read_rtc_registers(uint8_t time_arr[])
{
    uint8_t temp[7];
    uint8_t val1,val2,val3;

    i2c_start();                 // generate Start COndition
    i2c_wr(NAU7802_WR);           // send WRITE command

    
    i2c_wr( 0x00U );             // address from 0x00 i.e seconfs

    i2c_start();                 // generate Start COndition
    i2c_wr(RTC_RD);           // send READ command

    temp[0]=i2c_rd(ACK);           // read data from buffer
    temp[1]=i2c_rd(ACK);           // read data from buffer
    temp[2]=i2c_rd(ACK);           // read data from buffer
    temp[3]=i2c_rd(ACK);           // read data from buffer
    temp[4]=i2c_rd(ACK);           // read data from buffer
    temp[5]=i2c_rd(ACK);           // read data from buffer   
    temp[6]=i2c_rd(NACK);           // read data from buffer
    
    i2c_stop();                  // send Stop Condition
        
}


void rtc_wr_byte(uint8_t addr , uint8_t data)
{
    i2c_start();                 // generate Start COndition
    i2c_wr(RTC_WR);           // send WRITE command

    i2c_wr( addr );             //      address MSB

    i2c_wr(data);                // send data
    i2c_stop();                  // initiate Stop Condition
    ack_poll(RTC_WR);         // ACK polling

}



uint8_t rtc_rd_byte(uint8_t addr)
{
    uint8_t data;

    i2c_start();                 // generate Start COndition
    i2c_wr(RTC_WR);           // send WRITE command

    
    i2c_wr( addr );             //      address MSB

    i2c_start();                 // generate Start COndition
    i2c_wr(RTC_RD);           // send READ command

    data=i2c_rd(NACK);           // read data from buffer
    i2c_stop();                  // send Stop Condition

    return data;                 // return data from I2C buffer
}

 
void i2c_start(void)
{
    sda_input();
    scl_high();
    sda_output();
    sda_low();
    
    __no_operation();
    __no_operation();

    scl_low();
}



void i2c_stop(void)
{
    scl_low();
    sda_output();
    sda_low();
    
    __no_operation();
    __no_operation();
    __no_operation();
    
    scl_high();
    sda_input();
    
    __no_operation();
    __no_operation();
    __no_operation();   

    scl_low();
}



void bit_out(uint8_t data)
{
    scl_low();
    sda_output();
    
    if(data >> 7U)
    {
        sda_high();
    } 
    else
    {
        sda_low();
    } 

    __no_operation();
    __no_operation();
    
    scl_high();
    
    __no_operation();
    __no_operation();
    __no_operation();
    
    scl_low();
}


void bit_in(uint8_t *data)
{
    scl_low();
    sda_input();
    scl_high();
 
    __no_operation();
    __no_operation();
    __no_operation();   
    
    if(sda_read())
    {
        *data |= 0x01;
    } 
        
    scl_low();
}


uint8_t i2c_wr(uint8_t data)
{
    uint8_t i;                // loop counter
    uint8_t ack;              // ACK bit

    ack = 0U;
    for(i = 0U ; i < 8U ; i++)         // loop through each bit
    {
        bit_out(data);              // output bit
        data = data << 1;           // shift left for next bit
    }

    bit_in(&ack);                   // input ACK bit
    
    return ack;
    
}


uint8_t i2c_rd(uint8_t ack)
{
    uint8_t i;                // loop counter
    uint8_t ret = 0U;            // return value

    for(i = 0U ; i < 8U ; i++)           // loop through each bit
    {
        ret = ret << 1;             // shift left for next bit
        bit_in(&ret);               // input bit
    }

    bit_out(ack);                   // output ACK/NAK bit
    return ret;

}


void ack_poll(uint8_t control)
{
    uint8_t result = 1U;

    while(result)
    {
        i2c_start();            // generate Restart condition
        result = i2c_wr(control); // send control byte (WRITE command)
    }

    i2c_stop();                     // generate Stop condition
}
 

AlbertHall

Joined Jun 4, 2014
12,345
I2C lines need to be pulled low, but allowed to float high, via the pullup resistors. They should not be driven high.
I do not see the definition of scl_high() or sda_high() to check whether this is what you are doing.
 

JohnInTX

Joined Jun 26, 2012
4,787
In read_rtc_registers it looks like you are reading data into the temp array but never copying that data to the passed time_arr.
 
Top