Other Parts Discussed in Thread: BQ34110
Tool/software: Code Composer Studio
Hello,
I am currently having trouble using the I2C module on the F28335 MCU. I have been using the following Rx and Tx functions:
Uint16 I2CWriteReg(Uint16 reg, Uint16 data[], Uint16 data_size)
{
Uint16 i, Status;
Status = I2C_SUCCESS;
//
// Wait until the STP bit is cleared from any previous master communication
// Clearing of this bit by the module is delayed until after the SCD bit is
// set. If this bit is not checked prior to initiating a new message, the
// I2C could get confused.
//
if (I2caRegs.I2CMDR.bit.STP == 1)
{
return I2C_STP_NOT_READY_ERROR;
}
//
// Setup slave address
//
I2caRegs.I2CSAR = slaveAddress;
//
// Check if bus busy
//
if (I2caRegs.I2CSTR.bit.BB == 1)
{
return I2C_BUS_BUSY_ERROR;
}
I2caRegs.I2CCNT = 1 + data_size;
//
// Set up as master transmitter
// FREE + MST + TRX + IRS
//
I2caRegs.I2CMDR.all = 0x6E20;
//
// Setup number of bytes to send
// == register byte + (# of data[] buffer bytes)
//
// I2caRegs.I2CCNT = 1 + data_size;
//I2caRegs.I2CMDR.bit.STT = 0x1; // Send START condition
//I2caRegs.I2CMDR.bit.STP = 0x1; // STOP condition will be
// generated when I2CCNT is zero
//
// I2C module will send the following:
// register byte ==> data bytes ==> STOP condition
//
while(!I2caRegs.I2CSTR.bit.XRDY){} // Make sure data
// is ready to be written
I2caRegs.I2CDXR = reg;
#if NACK_CHECK // check if NACK was received
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
Status = I2C_ERROR;
return Status;
}
#endif
// Transmit Data Bytes followed by STOP condition
for (i=0; i< data_size; i++)
{
while(!I2caRegs.I2CSTR.bit.XRDY){
a++; //have been getting stuck here, so I put a timeout condition
if (a>8000)
{
errorcount++;
err_flag = 1;
return I2C_ARB_LOST_ERROR;
}
}
a = 0;
err_flag = 0;
I2caRegs.I2CDXR = data[i];
#if NACK_CHECK // check if NACK was received
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
Status = I2C_ERROR;
break;
}
#endif
}
// Data successfully written
return Status;
}
//
// I2CReadReg - This function reads data bytes from a slave
// device's register.
//
// INPUTS:
// - reg ==> Slave device register being read from
// - data[] ==> data buffer to store the bytes read from the
// slave device register
// - data_size ==> # of data bytes being received, size of data buffer
//
Uint16 I2CReadReg(Uint16 reg,
Uint16 data[], Uint16 data_size)
{
Uint16 i, Status=0;
//
// Wait until the STP bit is cleared from any previous master communication
// Clearing of this bit by the module is delayed until after the SCD bit is
// set. If this bit is not checked prior to initiating a new message, the
// I2C could get confused.
//
if (I2caRegs.I2CMDR.bit.STP == 1)
{
return I2C_STP_NOT_READY_ERROR;
}
//
// Setup slave address
//
I2caRegs.I2CSAR = slaveAddress;
//
// Check if bus busy
//
if (I2caRegs.I2CSTR.bit.BB == 1)
{
golbal_falg = 1;
return I2C_BUS_BUSY_ERROR;
}
golbal_falg = 0;
//
// 1. Transmit the slave address followed by the register
// bytes being read from
//
//
// Setup number of bytes to send
// == # of register bytes
//
I2caRegs.I2CCNT = 1;
//
// Set up as master transmitter
// FREE + MST + TRX + IRS
//
I2caRegs.I2CMDR.all = 0x4620;
I2caRegs.I2CMDR.bit.STT = 0x1; // Send START condition
while(!I2caRegs.I2CSTR.bit.ARDY) // Wait for slave address to be sent
{
a++;//have been getting stuck here, so I put a timeout condition
if (a>8000)
{
errorcount++;
err_flag = 1;
return I2C_ARB_LOST_ERROR;
}
if(I2caRegs.I2CSTR.bit.XSMT == 0)
{
break;
}
}
a = 0;
err_flag = 0;
#if NACK_CHECK // check if NACK was received
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
Status = I2C_ERROR;
return Status;
}
#endif
// Transmit Register Byte
while(!I2caRegs.I2CSTR.bit.XRDY)
{
a++;//have been getting stuck here, so I put a timeout condition
if (a>8000)
{
errorcount++;
err_flag = 1;
return I2C_ARB_LOST_ERROR;
}
}
a = 0;
err_flag = 0;
// is ready to be written
I2caRegs.I2CDXR = reg;
#if NACK_CHECK // check if NACK was received
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
Status = I2C_ERROR;
return Status;
}
#endif
// Wait for previous communication to complete
while(!I2caRegs.I2CSTR.bit.ARDY)
{
a++;//have been getting stuck here, so I put a timeout condition
if (a>8000)
{
errorcount++;
err_flag = 1;
return I2C_ARB_LOST_ERROR;
}
}
a = 0;
err_flag = 0;
//
// 2. Receive data bytes from slave device
//
//
// Set up as master receiver
// FREE + MST + IRS ==> (Master Receiver)
//
I2caRegs.I2CMDR.all = 0x4420;
//
// Setup number of bytes to receive
// == # of data bytes
//
I2caRegs.I2CCNT = data_size;
I2caRegs.I2CMDR.bit.STT = 0x1; // Send repeated START condition & Slave Addr
I2caRegs.I2CMDR.bit.STP = 0x1; // set STOP condition to be
// generated when I2CCNT is zero
#if NACK_CHECK // check if NACK was received
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
Status = I2C_ERROR;
return Status;
}
#endif
for (i=0; i< data_size; i++)
{
while(!I2caRegs.I2CSTR.bit.RRDY)
{
a++;//have been getting stuck here, so I put a timeout condition
if (a>8000)
{
errorcount++;
err_flag = 1;
return I2C_ARB_LOST_ERROR;
}
} // Make sure data*********************************************
a = 0; // is ready to be received
if(err_flag == 0)
{
data[i] = I2caRegs.I2CDRR; // Buffer the received byte
}
err_flag = 0;
}
// Data successfully read
return Status;
}
The problem is, when trying to use the I2CReadReg function, sometimes it will work as expected, but sometimes the data line will immediately be stuck high and the clock line will be stuck low. Even if it does work initially, it will usually eventually get stuck as well. The bus busy error will be returned. I have tried incorporating a timeout condition in main that will reset the I2C module if the BB, XRDY, RRDY flags etc are stuck being polled, but this doesn't seem to work. Could anyone give me some advice? Initially we thought it might be a noise issue (we are testing in a relatively noisy environment) but we are not so sure anymore. Information that may also be of interest:
-When the I2C lines are actually Tx/Rx'ing, the low voltage is not always 0 V, sometimes 700 mV (High is 3.3V).
-In main, we are using a write function once, then we are looping many read functions. It seems that on the first read function, the status error being returned is from the MCU being stuck polling for either XRDY or RRDY, but the rest of the read functions are returning the bus busy status error.
-Transmitting a specific write command to the slave (which resets the slave) will immediately hang the bus line 100% of the time. Transmitting any other write command will hang the bus line exactly 50% of the time (alternating between hanging the line and not hanging the line). Interestingly enough, stepping through the reset command line by line will not hang the bus line.