Part Number: LAUNCHXL-F280049C
Other Parts Discussed in Thread: BQ76952, C2000WARE
I am using a slightly modified version of the I2C master receiver function in C2000Ware_4_00_00_00\driverlib\f28004x\examples\i2c\i2cLib_FIFO_polling.c. to read registers from the BQ76952 battery monitor IC.
The original function uses the repeat mode but sometimes ends up reading 3 bytes of data instead of two.
I modified the function to use normal mode with a data count of two. After the register address byte is sent, I switch to normal, master-receive mode. I then set the data count to 2 and further set the start and stop bits in the I2C mode register. I expect a repeated start to be generated followed by the slave address and two byte read, but I don't see anything on the scope or the logic analyzer.
Please suggest if anything is wrong with the code.
uint16_t I2C_ReadReg(uint16_t reg_addr, uint16_t *reg_data, uint16_t NumOfDataBytes)
{
uint16_t status;
uint16_t attemptCount;
I2C_disableFIFO(MY_I2C_BASE); //Reset FIFOs
I2C_enableFIFO(MY_I2C_BASE);
// Write register address
status = I2C_TransmitSlaveAddress_ControlBytes(reg_addr);
if(status) {
return status;
}
uint16_t numofSixteenByte = NumOfDataBytes / I2C_FIFO_DEPTH; //FIFO is 16 bytes deep
uint16_t remainingBytes = NumOfDataBytes % I2C_FIFO_DEPTH;
// Switch to master receiver mode
//I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE));
I2C_setConfig(MY_I2C_BASE, I2C_MASTER_RECEIVE_MODE);
I2C_setDataCount(MY_I2C_BASE, NumOfDataBytes+1);
I2C_sendStartCondition(MY_I2C_BASE);
I2C_sendStopCondition(MY_I2C_BASE);
uint16_t i, count = 0, buff_pos=0;
//for(count=0; count < numofSixteenByte; ++count) { //Read 16 bytes at a time from RX FIFO
while(count < numofSixteenByte) {
status = handleNACK(MY_I2C_BASE);
if(status) {
return status;
}
count++;
attemptCount = 1;
while(!(I2C_getRxFIFOStatus(MY_I2C_BASE) == I2C_FIFO_RXFULL) && attemptCount <= 9 * (I2C_FIFO_RXFULL + 2U)) {
DEVICE_DELAY_US(I2C_DELAY_US);
attemptCount++;
}
for(i=0; i<I2C_FIFO_RXFULL; ++i) { // Transfer RX FIFO contents to RX buffer
reg_data[buff_pos] = I2C_getData(MY_I2C_BASE);
buff_pos++;
}
}
attemptCount = 1;
while(!(I2C_getRxFIFOStatus(MY_I2C_BASE) == remainingBytes) && attemptCount <= 9 * (remainingBytes + 2U)) {
DEVICE_DELAY_US(I2C_DELAY_US);
attemptCount++;
}
//I2C_sendStopCondition(MY_I2C_BASE);
for(i=0; i<remainingBytes; ++i) { // Transfer RX FIFO contents to RX buffer
reg_data[buff_pos] = I2C_getData(MY_I2C_BASE);
buff_pos++;
}
status = handleNACK(MY_I2C_BASE);
if(status) {
return status;
}
//I2C_disableFIFO(MY_I2C_BASE);
attemptCount = 1;
while(I2C_getStopConditionStatus(MY_I2C_BASE) && attemptCount <= 3U) {
DEVICE_DELAY_US(I2C_DELAY_US);
attemptCount++;
}
return SUCCESS;
}
/** Private Function Definitions **/
/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope: Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t I2C_TransmitSlaveAddress_ControlBytes(uint16_t ControlAddr)
{
uint16_t status;
uint16_t attemptCount = 1;
uint16_t NumOfAddrBytes = 1U;
do {
status = checkBusStatus(MY_I2C_BASE);
attemptCount++;
DEVICE_DELAY_US(I2C_DELAY_US);
} while(status & (attemptCount <= I2C_RETRIES));
if(status) {
return status; //Fail; Return bus busy or stop not ready error
}
I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_SEND_MODE|I2C_REPEAT_MODE));
I2C_setSlaveAddress(MY_I2C_BASE, DEV_ADDR); // Setup slave address
I2C_putData(MY_I2C_BASE, ControlAddr); // Put control address in transmit buffer
I2C_sendStartCondition(MY_I2C_BASE); // Send start condition
// DEVICE_DELAY_US(150U);
//
// status = handleNACK(MY_I2C_BASE);
// if(status) { // Retry once
// if(attemptCount <= I2C_RETRIES) {
// attemptCount++;
// I2C_setConfig(MY_I2C_BASE, (I2C_MASTER_SEND_MODE));
// I2C_sendStartCondition(MY_I2C_BASE);
// DEVICE_DELAY_US(I2C_DELAY_US);
// }
// else {
// return status; // Fail
// }
// }
attemptCount = 1;
while(I2C_getTxFIFOStatus(MY_I2C_BASE) && attemptCount <= 9 * (1U + NumOfAddrBytes + 2U))
{
status = handleNACK(MY_I2C_BASE);
if(status) {
return status;
}
attemptCount++;
DEVICE_DELAY_US(I2C_DELAY_US);
}
return SUCCESS;
}
/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope: Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t checkBusStatus(uint32_t base)
{
if(I2C_isBusBusy(base)) {
return ERR_BUS_BUSY;
}
if(I2C_getStopConditionStatus(base)) { // Check if the stop condition has not been already generated
return ERR_STOP_NOT_RDY;
}
return SUCCESS;
}
/*==============================================================================
Function Name:
--------------------------------------------------------------------------------
Scope: Private
--------------------------------------------------------------------------------
Description:
--------------------------------------------------------------------------------
Input Data:
--------------------------------------------------------------------------------
Return Value:
==============================================================================*/
uint16_t handleNACK(uint32_t base)
{
if(I2C_getStatus(base) & I2C_STS_NO_ACK) { //Status is NACK
I2C_clearStatus(base, I2C_STS_NO_ACK); //Clear NACK flag
I2C_sendStopCondition(base); //Set STP bit
return ERR_NACK_RCVD;
}
return SUCCESS;
}