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.
Hello,
I am working with the I2C communication with my TMS320F28386D and I am trying to achieve the following behavior.
I want the I2C module to send a Stop sequence after a message that is NACK'ed. At the moment my code only sends
stop sequences for messages that write out all of their bytes successfully. It is important, to the slave device that I am
writing to, that the stop sequence happens after every message so that it will recognize my retries.
In the TRM it says the following about the I2CMDR.STP register, "... STP has been set by the device to generate a STOP
condition when the internal data counter of the I2C module counts down to 0". And in the TRM it also says this about the
I2CNT Register, "The value written to I2CCNT is copied to an internal data counter. The internal data counter is decremented
by 1 for each byte transferred ... If a STOP condition is requested in the master mode (STP on I2CMDR), the I2C module terminates
the transfer with a STOP condition when the countdown is complete..." I try to leverage these points to generate a stop condition in my
state machine after a NACK. Any help is greatly appreciated, Thank You. I've attached a snippet of my code below.
switch(Substate) { case -1: { //NACK Detected EALLOW; I2caRegs->I2CSTR.bit.SCD = 1; I2caRegs->I2CMDR.bit.STP = 1; //Enabling the Stop condition upon CNT = 0; I2caRegs->I2CCNT = 0; //Trying to trick the I2C module that I have sent all of its bytes EDIS; if(masterWriteRetryCtr < masterWriteRetryLim) { //Code For Retry ... //End Code For Retry } else { Substate = 0; } break; } case 0: { // Master write complete. masterWriteRetryCtr = 0; break; } case 1: { // Transmit the next byte in Buffer, or end the master write process. if ((I2caRegs->I2CSTR.bit.XRDY) || (I2caRegs->I2CSTR.bit.ARDY)) { //If its ready to send if(I2caRegs->I2CSTR.bit.NACK) {Substate = -1;} else { I2caRegs->I2CDXR.all = Buffer[Ptr]; //Put next byte into transmit register Ptr++; } } if (I2caRegs->I2CSTR.bit.SCD == 1) { //If Stop Condition Substate = 0; EALLOW; I2caRegs->I2CSTR.bit.SCD = 1; EDIS;} break; } case 2: { // Configure to be Master. EALLOW; Ptr = 0; Substate = 1; I2caRegs->I2CCNT = ByteCount; //NUMBER OF BYTES TRANSMITTING I2caRegs->I2CMDR.bit.MST = 1; //Master I2caRegs->I2CMDR.bit.TRX = 1; //Transmitting I2caRegs->I2CMDR.bit.STP = 1; //Send I2C STOP Sequence when CNT == 0 I2caRegs->I2CSTR.bit.SCD = 1; // Clear any Detected Stops I2caRegs->I2CMDR.bit.STT = 1; EDIS; break; } }
Hi,
You can do the following in your code.
If a NACK is received, send a STOP and clear the NACK bit.
The following code snippet is from one of the examples included in C2000Ware. This uses driverlib APIs , you can do the same thing using bitfield.
uint16_t handleNACK(uint32_t base)
{
if(I2C_getStatus(base) & I2C_STS_NO_ACK)
{
I2C_clearStatus(base, I2C_STS_NO_ACK);
I2C_sendStopCondition(base);
return ERROR_NACK_RECEIVED;
}
return SUCCESS;
}
Best Regards
Siddharth
Hello Siddharth,
Thank you for your help.
I have one follow up regarding your answer.
I am trying to convert your example to its bitfield implementation.
For " I2C_clearStatus(base, I2C_STS_NO_ACK " I used "I2CaRegs.I2CSTR.bit.NACK = 1";
But for "I2C_sendStopCondition(base)" should I just use "I2CaRegs.I2CMDR.bit.STP = 1;" ?
Thank you Again for Your Help,
Daniel Brescia
Daniel,
Yes, you can use I2caRegs.I2CMDR.bit.STP = 0x1; for sending the STOP condition.
Best Regards
Siddharth
Daniel,
Glad that you were able to resolve it. Will close this thread.
Best Regards
Siddharth