This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
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.
Hi Colin,
Have you probed the bus to see what the waveforms look like when this issue occurs? You may need to try probing at both the Master and Slave sides in case only one side is not receiving correctly. Feel free to post screenshots of the waveforms here if you'd like me to look at them.
What device are you using as the slave? In your code, are you using the I2C FIFO mode, or non-FIFO?
Best,
Kevin
Hi Kevin,
Sorry for not replying. We were using the non-FIFO mode with a BQ34110 as a slave, and both sides seemed to be receiving correctly. Just an update on the problem: we couldn't actually find the source of the problem (it is likely noise, but this is hard to verify). We decided instead to just tell the microprocessor to quit the read or writing function if it got hung up while polling for a flag for too long, and then reset the I2C module if the bus lines themselves were hanging for too long. This might not be the best course of action, but it seems to work for the time being. Thanks for your help.