This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

INA226: INA226 reading problem.

Part Number: INA226
Other Parts Discussed in Thread: MSP430FR4133

I have a problem with reading INA226 registers.

void INA226_ReadReg(uint32_t slave_adr, uint8_t reg_addr, uint16_t *value)
{
    uint8_t val[2];
    
     /*----------first step - set register address to read from-----------*/
    
    //for a write operation R/Wn bit should be low
    uint8_t slave_address = slave_adr  & 0xFE;  
    
    I2C0_Start();
    
    /* send slave address with W/R bit */
    I2C0_write_byte(slave_address);
    I2C0_Wait();
    
    /* set register address */
    I2C0_write_byte(reg_addr);
    I2C0_Wait();
    
    
    /*-----------second step - read from the written register address-----*/
    
     //slave address for read
    slave_address = slave_adr | 0x01;
    
    //I2C0_Start();
    I2C0_RepeatedStart();
    
    I2C0_write_byte(slave_address);
    I2C0_Wait();
    
    // Put in Rx Mode
    I2C0_C1 &= ~I2C_C1_TX_MASK;
    
    // Ensure TXAK bit is 0   
    I2C0_C1 &= ~I2C_C1_TXAK_MASK;  

    // Turn off ACK since this is second to last byte being read
    //I2C0_C1 |= I2C_C1_TXAK_MASK;
   
    // Dummy read  - why??? 
    val[0] = I2C0_D;
    I2C0_Wait();
    
    val[0] = I2C0_D;
    I2C0_Wait();
    
    //disable aknowledge
    I2C0_C1 |= I2C_C1_TXAK_MASK;
    
    val[1] = I2C0_D;
    I2C0_Wait();
    
    I2C0_Stop();
    
    *value = (val[0] << 8) | val[1];
    
}

This way I read the right values from INA226_MANUFACTURE_ID(0x5449) and INA226_DIE_ID(0x2260) registers.
As you can see I need a dummy read to get it right.

But when I trigger a measurement and then read the voltage, shunt, current registers - I get some wrong values.
What's wrong with my register reading algorithm?

  • Hello Evgeny,

    Thanks for using Texas Instruments in your design. From the code you posted I suspect the slave address you are using is the issue. Some microcontrollers will have the read and write bit controlled by a separate register. To illustrate this point, I will use the MSP430FR4133 as an example. Assuming I do the following code:

    slave_adr = 0x40; //address should only have 7 bits, slave's A1 and A0 tied to gnd
    UCB0I2CSA = slave_adr; //Register for slave address that will be transmitted
    UCB0CTLW0 &= ~UCTR; //microcontroller I2C setup register listed as UCBxCTLW0 in the user Guide. UCTR = 0x10, this bit determines whether master
    //is setup to transmit or receive
    I would thereby expect the following bit stream on the SDA Line: start,1,0,0,0,0,0,0,0(Read),0 (Acknowledge from slave).

    Your microcontroller may be different. So I would either verify with the user guide or alternatively with oscilloscope shots.

    If you still have issues, I would recommend attaching your oscilloscope shots, so that we may have a better idea of what the interchange between your master and slave actually looks like.
  • Hello Evgeny,

    Are you still getting the wrong values from your registers?
  • I have a very strange situation - on a logic analyzer I see a right value but when I read it I get a wrong result.

    Can you show a read function for MSP430F?

  • Hello Evgeny,

    Below I pasted some code that  shows how to make a MSP430FR4133 master read 1 byte from a slave with the assigned address of 0x48.  Also for future reference, for many of our microcontrollers, you can find sample code posted under the "Tools & Software" tab on the product page (http://www.ti.com/product/MSP430FR4133/toolssoftware).

    Figure 1: Sample Code Location

    // Configure USCI_B0 for I2C mode

       UCB0CTLW0 |= UCSWRST;                   // Software reset enabled

       UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync

       UCB0CTLW1 |= UCASTP_2;                  // Automatic stop generated

                                               // after UCB0TBCNT is reached

       UCB0BRW = 0x0008;                       // baudrate = SMCLK / 8

       UCB0TBCNT = 0x0001;                     // number of bytes to be received

       UCB0I2CSA = 0x0048;                     // Slave address

       UCB0CTL1 &= ~UCSWRST;

       UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;

       while (1)

       {

           __delay_cycles(2000);

           while (UCB0CTL1 & UCTXSTP);         // Ensure stop condition got sent

           UCB0CTL1 |= UCTXSTT;                // I2C start condition

           __bis_SR_register(LPM0_bits|GIE);   // Enter LPM0 w/ interrupt

       }

    }

    //***************************************************************************

    //Interrupt Service Routine

    //***************************************************************************

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

    #pragma vector = USCI_B0_VECTOR

    __interrupt void USCIB0_ISR(void)

    #elif defined(__GNUC__)

    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)

    #else

    #error Compiler not supported!

    #endif

    {

     switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))

     {

       case USCI_NONE:          break;         // Vector 0: No interrupts

       case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG

       case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG

         UCB0CTL1 |= UCTXSTT;                  // I2C start condition

         break;

       case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG

       case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG

       case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3

       case USCI_I2C_UCTXIFG3:  break;         // Vector 14: TXIFG3

       case USCI_I2C_UCRXIFG2:  break;         // Vector 16: RXIFG2

       case USCI_I2C_UCTXIFG2:  break;         // Vector 18: TXIFG2

       case USCI_I2C_UCRXIFG1:  break;         // Vector 20: RXIFG1

       case USCI_I2C_UCTXIFG1:  break;         // Vector 22: TXIFG1

       case USCI_I2C_UCRXIFG0:                 // Vector 24: RXIFG0

         RXData = UCB0RXBUF;                   // Get RX data

         __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0

         break;

       case USCI_I2C_UCTXIFG0:  break;         // Vector 26: TXIFG0

       case USCI_I2C_UCBCNTIFG:                // Vector 28: BCNTIFG

         P1OUT ^= BIT0;                        // Toggle LED on P1.0

         break;

       case USCI_I2C_UCCLTOIFG: break;         // Vector 30: clock low timeout

       case USCI_I2C_UCBIT9IFG: break;         // Vector 32: 9th bit

       default: break;

     }

    }