I2C bit banging and interfacing analog ADC

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
535
1. I need to interface NAu7802 datasheet attached.
2. MCU is operating at 16Mhz, writing I2C code by bit banding.
3. took reference from Microchip AN1488 note for bit banding and wrote below code.
4. When i tested on hardware, it runs but nau7802_rd_byte(0x1f) don not return 0x0f, which is id .
5. What is wrong in this code
6. One thing I dont understand in nau7802_wr_byte() function is sending ack_poll(NAU7802_WR); , what does it do?
Why sending address again ?
7. is there anything wrong in code below?


Code:
#define NAU7802_REG_PU_CTRL            0x00
#define NAU7802_REG_CTRL1            0x01


#define  NAU7802_BIT_PU_CTRL_PUA            0x04
#define  NAU7802_BIT_PU_CTRL_PUD          0x02
#define  NAU7802_BIT_PU_CTRL_RR            0x01


#define  NAU7802_BIT_VLDO_3V3            0x20



void nau7802_init(void)
{
   uint8_t temp;

    scl_output();
    scl_high();
    
    
/* Send Reset command into NAU7802 */     
    nau7802_wr_byte(NAU7802_REG_PU_CTRL , NAU7802_BIT_PU_CTRL_RR);
    
//waitfor 2000us       
    delay_us(2000)
    
/* Enable PUD to power on the chip digital logic */
    nau7802_wr_byte(NAU7802_REG_PU_CTRL , NAU7802_BIT_PU_CTRL_PUD);
      
    
/* Wait power up ready */   
    do
    {
        temp = nau7802_rd_byte(NAU7802_REG_PU_CTRL);
            
    }while( 0U == (temp & (1U << 3U) ) );       
    
    
    temp = nau7802_rd_byte(0x1f);
    if(temp == 0x0f)
    {
        //ok;
    }
    
    while(1)
    {
    
    }   

}



#define ACK           0x00
#define NACK          0x80
#define NAU7802_WR    0x54                   // WRITE instruction
#define NAU7802_RD    0x55                   // READ instruction



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

    i2c_wr( addr );             //      address MSB

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

}



uint8_t nau7802_rd_byte(uint8_t addr)
{
    uint8_t data;

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

    
    i2c_wr( addr );             //      address MSB

    i2c_start();                 // generate Start COndition
    i2c_wr(NAU7802_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
}
 

Attachments

sailorjoe

Joined Jun 4, 2013
363
Do you have external pull-up resistors on the SCLK and the SDIO lines? I know the NAU7802 has large default pull-ups of 50K, but your I/O will run very slowly with those. Try 4K resistors from each line to the digital power supply.

Can you see the signals going on the lines with an o-scope? What do you see?

You wrote that you are sending the I/O signals by "bit banding." I think you meant to say "bit banging."

I'll check your code next.
 

n1ist

Joined Mar 8, 2009
186
Since you didn't mention what processor you are using, what mode SCL and SDA are in, or the code for sda_high() et al, it is hard to guess. I2C is an open drain or open collector bus. The processor and other devices on the bus can only drive it low; to set a high, they turn off the bus and let the pullup resistors pull them high. You can simulate that by setting the pins as input for generating a "1" and by setting them as outputs driving them low to generate a "0".

If you have a scope or at least a cheap logic analyzer, you can check what's really happening on the bus.
/mike
 

upand_at_them

Joined May 15, 2010
350
What is the address of the device? All I2C devices have addresses, which allows the bus to work for multiple devices. The first byte sent after Start() has to be the device address.
 
Top