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.

CCS/MSP430FR2476: I2C Communication not reading in real data

Part Number: MSP430FR2476


Tool/software: Code Composer Studio

I am trying to program I2C communication between the MSP430 and a battery gauge (LTC2943). My read functions are only returning zeros. This is the read function:
void i2cReceive(uint8_t regAddress, uint8_t buffer, uint8_t bufferSize){
    uint8_t i;

    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, LTC2943_SLAVE_ADDRESS);
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
    EUSCI_B_I2C_enable(EUSCI_B0_BASE);

    while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE));
    EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);

    // switch to receiver mode
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);

    for(i=0; i<bufferSize; i++){
        buffer = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
        buffer++;
    }

    EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
}

And this is one of the functions to read from a specific register:

uint8_t getControl(){
    uint8_t control = 0;
    i2cReceive(CONTROL_ADDRESS, control, sizeof(control));

    return control;
}

Sometimes it would get stuck in this while loop in i2cReceive():
while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE)); 
When I commented that line out, it would run, but every register would return zero. I also tried using different functions like EUSCI_B_I2C_slaveGetData()  but that just returned 255 each time.
  • >    EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
    >    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    I think you need to send regAddress to the device somewhere in here, maybe something like
    >    EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, regAddress);
    >    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    >    EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);

     

     

  • You're right, I had forgotten to send the register address. I updated my code to include this, but I'm getting the same result. 

    Here's my updated code:

    void i2cReceive(uint8_t regAddress, uint8_t *buffer, uint8_t bufferSize){
        uint8_t i;
    
        EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, LTC2943_SLAVE_ADDRESS);
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
        EUSCI_B_I2C_enable(EUSCI_B0_BASE);
    
    
        EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
        EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE, regAddress);
    
        // switch to receiver mode
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    
        EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    
        for(i=0; i<bufferSize; i++){
            *buffer = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
            buffer++;
        }
    
        EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
        while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE));
    }
    
    uint8_t getControl(){
        uint8_t control = 0;
        i2cReceive(CONTROL_ADDRESS, &control, sizeof(control));
    
        return control;
    }

  •  > EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
     > EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE, regAddress);

     slavePutData doesn't do what you want (it doesn't wait for TXIFG). Did masterSendSingleByte not work?

  • If I change it to masterSendSingleByte it gets stuck in this while loop within masterSendSingleByte

    //Poll for transmit interrupt flag. while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

  • Just to be clear: SendSingleByte does a Start, a transmit, and a Stop, so if you use it you shouldn't call SendStart separately.

    What is the value of LTC2943_SLAVE_ADDRESS? On the one hand, I don't think you would have gotten this far if it were incorrect, but on the other hand that line of code is where I would expect it to fail if you were getting a NACK. Based on data sheet (2943FA)  Fig 5, I would expect it to be 0x64.

  • I got 0x64 for the address as well. I just commented out the sendStart before the sendSingleByte and it's still getting stuck in the same while loop.

  • Looking at the source, EUSCI_B_I2C_masterReceiveMultiByteNext doesn't wait for RXIFG to be set. (No this wasn't obvious to me either.) The variant that does wait for RXIFG is EUSCI_B_I2C_masterReceiveSingle.

    I don't have your device, but I was able to read (repeatedly) the WHO_AM_I (0x0F) register from an LIS3DH using this version:

    void i2cReceive(uint8_t regAddress, uint8_t *buffer, uint8_t bufferSize){
        uint8_t i;
    
        EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, LTC2943_SLAVE_ADDRESS);
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
        EUSCI_B_I2C_enable(EUSCI_B0_BASE);
    #if BMC
        EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, regAddress);
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
        EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
    #else
        EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
        EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE, regAddress);
        // switch to receiver mode
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
        EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    #endif // BMC
    
        for(i=0; i<bufferSize; i++){
    #if BMC
            *buffer = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);
    #else
            *buffer = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
    #endif
            buffer++;
        }
        EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
        while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE));
    }
    

    [Edit: Fixed the duplicate code (it still works). Posting it took a few tries.]

**Attention** This is a public forum