MSP432P401R: I2C - Receiving 2 Bytes when I am supposed to be receiving 1 - Using Driverlib masterReceiveSingleByte

Part Number: MSP432P401R

I am trying to communicate with a BQ27441 Battery Fuel Guage. My I2C communication is working fine for the most part, but there is a part in the code where I need to receive a single byte checksum (anything more and errors occur). When I use the driverlib function to receive a single byte, I get 2 bytes!

I have attached the driverlib setup code, the problem code, and my interrupt code.

I also included the logic analyzer output of what is happening on the I2C lines. As you can see below, I write 0x60 for the register, then I try and read a single byte and I get back 0x00+ACK AND 0x00+NACK. 

Setup:

  • I2C Pins 6.6 & 6.7
  • 1K pullup
  • 100kbps
  • Only the BQ27441 is on the bus
  • The code was originally from a driver lib example, but has been modified heavily to suit our needs

Problem code:

    //send block checksum command to check the checksum
    EUSCI_TXBuffer &= 0x00;                                                        // Clear Transmit Buffer
    MAP_I2C_masterSendSingleByte(EUSCI_module, BQ27441_EXTENDED_CHECKSUM);

    NUM_OF_REC_BYTES = 1;
    MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE);                       // Set to Receive mode
    MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);         // Enable Receive Interrupt
    uint8_t OLD_Csum = MAP_I2C_masterReceiveSingleByte(EUSCI_module);
    rxFlag = 0;
    MAP_I2C_disableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);     // Disable receive interrupt
    
    
    MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_TRANSMIT_MODE);                   // Set I2C mode to transmit
    xferIndex = 0;                                                              // Clear the RXData index

Setup code:

void FuelGauge_Setup()
{
    // Select Port 6 for I2C - Set Pin 4, 5 to input Primary Module Function, (UCB1SIMO/UCB1SDA, UCB1SOMI/UCB1SCL).
#if SDApin == GPIO_PIN6 && I2Cport == GPIO_PORT_P6
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(I2Cport, SDApin + SCLpin, GPIO_SECONDARY_MODULE_FUNCTION);
#else
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(I2Cport, SDApin + SCLpin, GPIO_PRIMARY_MODULE_FUNCTION);
#endif
    // Initializing I2C Master to SMCLK at 100kbs with no auto-stop
    MAP_I2C_initMaster(EUSCI_module, &i2cConfig);

    // Specify slave address
    MAP_I2C_setSlaveAddress(EUSCI_module, BQ27441_I2C_ADDRESS);

    // Set Master in transmit mode
    MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_TRANSMIT_MODE);

    // Enable I2C Module to start operations
    MAP_I2C_enableModule(EUSCI_module);

    // Enable and clear the interrupt flags todo make transmit interrupts in the define page
    MAP_I2C_clearInterruptFlag(EUSCI_module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0);

    //Enable master Receive interrupt
    MAP_Interrupt_enableInterrupt(EUSCI_moduleINT);
}

Interrupt code:

void EUSCIB3_Receive(void)
{
  uint_fast16_t status;                                                                   // Flag status

  status = MAP_I2C_getEnabledInterruptStatus(EUSCI_module);                               // Grab any flags that are triggered
  MAP_I2C_clearInterruptFlag(EUSCI_module, status);                                       // Clear interrupt flags that are triggered

    if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)                                            // If the interrupt flag for receive has been triggered
    {
      if(NUM_OF_REC_BYTES > 1)                                                            // If number of receive bytes has been set to a value over 1
      {
          if(xferIndex == NUM_OF_REC_BYTES - 2)                                           // When xferIndex is on the third to last byte
          {
              MAP_I2C_masterReceiveMultiByteStop(EUSCI_module);
              RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module);     // Receive and store byte into RXData
          }
          else if(xferIndex == NUM_OF_REC_BYTES - 1)                                      // When xferIndex is on the second to last byte
          {
              RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module);     // Receive and store byte into RXData
              MAP_I2C_disableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);     // Disable receive interrupt
              MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_TRANSMIT_MODE);                   // Set I2C mode to transmit
              xferIndex = 0;                                                              // Clear the RXData index
              rxFlag = 1;                                                                 // Set receive interrupt flag high
              NUM_OF_REC_BYTES = 0;                                                       // Clear NUM_OF_REC_BYTES
          }
          else                                                                            // Executed until xferIndex is within 2 from the length of NUM_OF_REC_BYTES
          {
              RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module);
          }
      }else{
            rxFlag = 1;                                                                 // Set receive interrupt flag high
            NUM_OF_REC_BYTES = 0;                                                       // Clear NUM_OF_REC_BYTES
      }
    }


}

14 Replies