Hello! I'm trying to read BMA280 accelerometer over I2C using MSP432. This is the sequence I'm trying to achieve in order to read the chip ID:
1. Send start and register address;
2. Send (re)start and read one byte;
3. Send STOP.
The problem is that STOP is not sent after the receiving the first (and only) byte, as I want. Instead, it is sent after receiving a second byte.
This is my code:
eUSCI_I2C_MasterConfig i2cConfig =
{
EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
#ifdef USE_CPU_CLOCK_DCO_24MHz
12000000, // SMCLK
#endif
#ifdef USE_CPU_CLOCK_XTAL_48MHz
24000000, // SMCLK
#endif
EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // I2C Clock
0, // No byte counter threshold
EUSCI_B_I2C_NO_AUTO_STOP // No Autostop
};
bool I2C_init(uint32_t moduleInstance)
{
/* Select I2C function for I2C pins */
switch (moduleInstance)
{
case EUSCI_B0_BASE:
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
break;
case EUSCI_B1_BASE:
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN4 | GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
break;
case EUSCI_B2_BASE:
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
break;
case EUSCI_B3_BASE:
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
break;
}
/* Initializing I2C Master */
MAP_I2C_initMaster(moduleInstance, &i2cConfig);
/* Enable I2C Module to start operations */
MAP_I2C_enableModule(moduleInstance);
MAP_I2C_clearInterruptFlag(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
MAP_I2C_enableInterrupt(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
TimerA2_delayMiliseconds(100);
return true;
}
int I2C_sendReadBytes(uint32_t moduleInstance, unsigned char* txBuffer, unsigned char* rxBuffer, int noBytesTx, int noBytesRx, int timeout)
{
/* Making sure the last transaction has been completely sent out */
int timeout2 = timeout;
while (MAP_I2C_masterIsStopSent(moduleInstance) && --timeout2);
if (timeout2 == 0)
return -1;
//MAP_Interrupt_enableSleepOnIsrExit();
/* Initiate start and send first character */
if (!MAP_I2C_masterSendMultiByteStartWithTimeout(moduleInstance, txBuffer[0], timeout))
return -1;
int i;
for (i = 1; i < noBytesTx - 1; i++)
{
if (!MAP_I2C_masterSendMultiByteNextWithTimeout(moduleInstance, txBuffer[i], timeout))
return -1;
}
if (noBytesTx > 1)
{
if (!MAP_I2C_masterSendSingleByteWithTimeout(moduleInstance, txBuffer[noBytesTx - 1], timeout)) // If for is from i..noBytes, it does not transmit the last byte; do not know why
return -1;
}
timeout2 = timeout;
while(!(MAP_I2C_getInterruptStatus(moduleInstance, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)) && --timeout2);
if (timeout2 == 0)
return -1;
MAP_I2C_masterReceiveStart(moduleInstance);
if (noBytesRx == 1)
{
i = 0;
timeout2 = timeout;
while(!(MAP_I2C_getInterruptStatus(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0)) && --timeout2);
if (timeout2 == 0)
return -1;
MAP_I2C_masterReceiveMultiByteStop(moduleInstance);
rxBuffer[i] = MAP_I2C_masterReceiveMultiByteNext(moduleInstance);
//rxBuffer[i] = MAP_I2C_masterReceiveSingleByte(moduleInstance); // Does not work
//rxBuffer[i] = MAP_I2C_masterReceiveMultiByteFinish(moduleInstance); // Hangs
}
else
{
i = 0;
for(i = 0 ; i < noBytesRx - 1; i++)
{
timeout2 = timeout;
while(!(MAP_I2C_getInterruptStatus(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0)) && --timeout2);
if (timeout2 == 0)
return -1;
rxBuffer[i] = MAP_I2C_masterReceiveMultiByteNext(moduleInstance);
}
timeout2 = timeout;
while(!(MAP_I2C_getInterruptStatus(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0)) && --timeout2);
if (timeout2 == 0)
return -1;
MAP_I2C_masterReceiveMultiByteStop(moduleInstance);
/*timeout2 = timeout;
while(!(MAP_I2C_getInterruptStatus(moduleInstance, EUSCI_B_I2C_RECEIVE_INTERRUPT0)) && --timeout2);
if (timeout2 == 0)
return -1;*/
rxBuffer[i] = MAP_I2C_masterReceiveMultiByteFinish(moduleInstance);
}
return 0;
}
Logic analyzer capture:
As you can see, I need to issue the stop after 0xFB is received. As stated at p. 103 of the accelerometer's datasheet, the master should send NACK + STOP to end the transfer, but this happens at the second byte, not at the first one as I needed.
I've tried the code presented in this topic, but it does not work as expected. This is the logic analyzer capture:
Can anybody help me out with this issue?

