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.

TMS320F280039C: I2C Master (F280039C) can't communicate with INA227 – no ACK

Part Number: TMS320F280039C
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

[I2C Master (F280039C) can't communicate with INA227 – no ACK]

Hi, I'm using a TI F280039C LaunchPad to communicate over I2C with an INA227 power monitor located on a custom PCB. The INA227 is already connected to a PIC microcontroller, but the PIC is not actively using I2C in this scenario—it's just powering the INA227. 

Tools️ System Setup Overview:

F280039C LaunchPad configured as I2C master INA227 is on another PCB, powered through the PIC (which is idle)

Shared GND confirmed between both boards

Wiring: I2C lines from LaunchPad connected via test points on the INA227 board Pull-up resistors: 10kΩ to 3.3V already present on INA227/PIC board 1kΩ pull-ups to 3.3V on LaunchPad side SDA: GPIO34 SCL: GPIO51

 Chart with upwards trend Oscilloscope Observations:

With both 10kΩ + 1kΩ pull-ups connected: SDA: two short LOW pulses then HIGH, repeating for every command

SCL: consistent 10 pulses per transaction, repeating INA227 does not ACK After removing the 1kΩ pull-up (only 10k remains):

SDA: waveform changes to a sawtooth-like pattern SCL: still 10 pulses per burst, repeating No ACK observed When removing the 3.3V pull-up voltage (i.e., disconnecting VCC from the pull-up resistors):

Both SDA and SCL lines go flat (no toggling activity) 

White check mark What’s Working / Confirmed: INA227 is powered (PIC board active, LED confirms code is running) INA227 works correctly when communicating with the PIC Pull-up voltage and GND are shared F280039C I2C generates start/stop, clock signals. Should INA227 I2C lines be buffered or protected when shared between LaunchPad and PIC?

Thanks in advance for any help in narrowing down the root cause! 

  • Hi Antony,

    Can you provide some screenshots of the I2C communication line compared between the PIC and the F280039C board?

    Also, how is the F280039C LaunchPad? Are you powering through the BoosterPack headers and isolating just the debugger signals?

    Are you using our example software for I2C communication or do you have custom code? Do note that F280039C is 16-bit addressable so it is better to reference our example code to account for this

    Regards,

    Peter

  • Hi Peter,

    Thanks for reaching out!

    • Power: The F280039C LaunchPad is currently powered via the USB port.

    • Communication with INA227 (via I2C): The INA227 sensor is powered externally (3.3V) 

    • I am not using the BoosterPack headers to power external devices — only signal lines for I2C are connected.

    • I am not isolating just the debugger signals; the full LaunchPad USB power and debug interface are active.

    • I've observed the I2C waveforms with a logic analyzer and oscilloscope.

    • SCL: Shows regular clock pulses (start, 8–9 clocks, stop).

    • SDA: Transmits address and data bytes — however, the slave does not ACK, and the waveform looks the same whether the INA227 is connected or not.

    • I'm using custom code (based on TI's driverlib functions).
  • Hi Antony,

    Can you verify what the target address you are using is? As well, if you can provide the I2C initialization and code that you are using, that will be helpful

    Regards,

    Peter

  • Hi peter, 

    this is code of i2c initialization . it is generates using sysconfig.

    void I2C1_init(){
        I2C_disableModule(I2C1_BASE);
        I2C_initController(I2C1_BASE, DEVICE_SYSCLK_FREQ, I2C1_BITRATE, I2C_DUTYCYCLE_33);
        I2C_setConfig(I2C1_BASE, I2C_CONTROLLER_SEND_MODE);
        I2C_disableLoopback(I2C1_BASE);
        I2C_setOwnAddress(I2C1_BASE, I2C1_OWN_ADDRESS);
        I2C_setTargetAddress(I2C1_BASE, I2C1_TARGET_ADDRESS);
        I2C_setBitCount(I2C1_BASE, I2C_BITCOUNT_8);
        I2C_setDataCount(I2C1_BASE, 0);
        I2C_setAddressMode(I2C1_BASE, I2C_ADDR_MODE_7BITS);
        I2C_disableFIFO(I2C1_BASE);
        I2C_clearInterruptStatus(I2C1_BASE, I2C_INT_REG_ACCESS_RDY | I2C_INT_STOP_CONDITION);
        I2C_enableInterrupt(I2C1_BASE, I2C_INT_REG_ACCESS_RDY | I2C_INT_STOP_CONDITION);
        I2C_setEmulationMode(I2C1_BASE, I2C_EMULATION_STOP_SCL_LOW);
        I2C_enableModule(I2C1_BASE);
    }     
    #define I2C1_BASE I2CB_BASE
    #define I2C1_BITRATE 400000
    #define I2C1_TARGET_ADDRESS 64
    #define I2C1_OWN_ADDRESS 0
    #define I2C1_MODULE_CLOCK_FREQUENCY 10000000
  • Hi Antony,

    It looks like this initialization code looks fine and I believe that is the correct target address for this INA227 device. Can you share the code that does the read and writes to the I2C module?

    Regards,

    Peter

  • Hi Peter,

    Thanks for your response. Below is the code snippet I’m currently using for communicating with the INA227 via I2C:

    uint8_t id;
            I2C_readBytes(0x40, 0x06, &id, 1);
            I2C1_writeReg(I2C1_TARGET_ADDRESS, 0x01, 0xAB);
            uint8_t val = I2C1_readReg(I2C1_TARGET_ADDRESS, 0x01);
     
    bool I2C_readBytes(uint16_t devAddr, uint16_t reg, uint8_t *data, uint16_t len)
    {
        uint32_t timeout;

        // Send register pointer first (write phase)
        timeout = I2C_TIMEOUT;
        while(I2C_isBusBusy(I2CB_BASE) && --timeout);
        if(timeout == 0) return false;

        I2C_setTargetAddress(I2CB_BASE, devAddr);
        I2C_setDataCount(I2CB_BASE, 1); // sending register pointer
        I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_SEND_MODE);
        I2C_sendStartCondition(I2CB_BASE);
        I2C_putData(I2CB_BASE, reg);

        timeout = I2C_TIMEOUT;
        while(!I2C_getStopConditionStatus(I2CB_BASE) && --timeout);
        if(timeout == 0) return false;

        //I2C_clearStopConditionStatus(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_STOP_CONDITION);

        // Now read phase
        I2C_setTargetAddress(I2CB_BASE, devAddr);
        I2C_setDataCount(I2CB_BASE, len);
        I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_RECEIVE_MODE);
        I2C_sendStartCondition(I2CB_BASE);
        uint16_t i;
        for(i = 0; i < len; i++)
        {
            timeout = I2C_TIMEOUT;
            //while(!I2C_isRxReady(I2CB_BASE) && --timeout);
            if(timeout == 0) return false;

            data[i] = I2C_getData(I2CB_BASE);
        }

        timeout = I2C_TIMEOUT;
        while(!I2C_getStopConditionStatus(I2CB_BASE) && --timeout);
        if(timeout == 0) return false;

        //I2C_clearStopConditionStatus(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_STOP_CONDITION);

        return true;
    }
    void I2C1_writeReg(uint16_t slaveAddr, uint8_t reg, uint8_t data)
    {
        I2C_setTargetAddress(I2CB_BASE, I2C1_TARGET_ADDRESS);
        I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_SEND_MODE);
        I2C_setDataCount(I2CB_BASE, 2);

        I2C_putData(I2CB_BASE, reg);
        I2C_putData(I2CB_BASE, data);

        I2C_sendStartCondition(I2CB_BASE);
        I2C_sendStopCondition(I2CB_BASE);

        while(!I2C_getStopConditionStatus(I2CB_BASE));  // Wait for stop
        //I2C_clearStopConditionStatus(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_STOP_CONDITION);
    }
    uint8_t I2C1_readReg(uint16_t slaveAddr, uint8_t reg)
    {
        uint8_t readData;

        // First write the register address
        I2C_setTargetAddress(I2CB_BASE, I2C1_TARGET_ADDRESS);
        I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_SEND_MODE);
        I2C_setDataCount(I2CB_BASE, 1);

        I2C_putData(I2CB_BASE, reg);
        I2C_sendStartCondition(I2CB_BASE);
        while(!I2C_getStopConditionStatus(I2CB_BASE));
        //I2C_clearStopConditionStatus(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_STOP_CONDITION);

        // Now read the data
        I2C_setConfig(I2CB_BASE, I2C_CONTROLLER_RECEIVE_MODE);
        I2C_setDataCount(I2CB_BASE, 1);

        I2C_sendStartCondition(I2CB_BASE);
        I2C_sendStopCondition(I2CB_BASE);

        while(!I2C_getRxFIFOStatus(I2CB_BASE));  // Wait for data
        readData = I2C_getData(I2CB_BASE);

        while(!I2C_getStopConditionStatus(I2CB_BASE));
        //I2C_clearStopConditionStatus(I2CB_BASE);
        I2C_clearInterruptStatus(I2CB_BASE, I2C_INT_STOP_CONDITION);

        return readData;
    }  

    Please let me know if you see anything I might have missed regarding addressing or any specifics to consider with the INA227 and the F28003x family.

  • Hi Antony,

    Do you see the timeout getting triggered a lot in the I2C communication? What value are you using for the timeout define? Can you try to forego the timeout for now and allow the I2C line to clock stretch appropriately in case the INA227 is taking too long to respond? 

    Regards,

    Peter