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 } } }