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 writing an i2c interface using the driver lib. In order to read the temperature of different "transistors" i need use the code from the driver lib:
uint16_t readData( struct I2CMsg *msg ) { // // Wait until the STP bit is cleared from any previous master // communication. if(I2C_getStopConditionStatus(I2CA_BASE)) { return(ERROR_STOP_NOT_READY); } // // Setup address of control of temp sensors I2C_setSlaveAddress(I2CA_BASE, TMP_422_ADD); // send address of register to read // when this is ready, interrupt handles the read process if(msg->msgStatus == MSG_STATUS_SEND_NOSTOP) { // // Check if bus busy if(I2C_isBusBusy(I2CA_BASE)) { return(ERROR_BUS_BUSY); } // // Send data to setup EEPROM address I2C_setDataCount(I2CA_BASE, 1); I2C_putData(I2CA_BASE, msg->pointer); I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE); I2C_sendStartCondition(I2CA_BASE); } return(SUCCESS); }
in the interrupt ISR:
i2cISR() { .... if(intSource == I2C_INTSRC_STOP_CONDITION) { // // If completed message was writing data, reset msg to inactive state if(currentMsgPtr->msgStatus == MSG_STATUS_WRITE_BUSY) { currentMsgPtr->msgStatus = MSG_STATUS_INACTIVE; } else { if(currentMsgPtr->msgStatus == MSG_STATUS_SEND_NOSTOP_BUSY) { currentMsgPtr->msgStatus = MSG_STATUS_SEND_NOSTOP; } // // If completed message read else if(currentMsgPtr->msgStatus == MSG_STATUS_READ_BUSY) { for(i=0; i < currentMsgPtr->numBytes; i++) { currentMsgPtr->msgBuffer[i] = I2C_getData(I2CA_BASE); } // make possible to write message again currentMsgPtr->msgStatus = MSG_STATUS_SEND_NOSTOP; } } } ... }
This works ok, if I time-out between sending the write condition:
write(sensorMsgs1)
timeout
write(sensoreMsg2)
timeout etc.
My idea was to :
void readPcBSensors( void ) { static pcbSelect selectedSensor = TEMP_1; if( I2C_isBusBusy(I2CA_BASE) ) { switch( selectedSensor ) { case TEMP_1: if( readPcbTemp1( ) == SUCCESS ) { selectedSensor = TEMP_2; } else { NOP(); } break; case TEMP_2: ...... } }
With:
uint16_t readPcbTempLoc( void ) { uint16_t error = 1; // // Check incoming message status if(i2cMsgInExTempLoc.msgStatus == MSG_STATUS_SEND_NOSTOP) { // // Send EEPROM address setup // currentMsgPtr = &i2cMsgInExTempLoc; error = readData( &i2cMsgInExTempLoc ); // // Update current message pointer and message status if // read success else try again next time if( error == SUCCESS) { i2cMsgInExTempLoc.msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY; } else { NOP; } } return error; }
The Problem is, that i never get to writing data since:
if(I2C_isBusBusy(I2CA_BASE) is always true
What did i get wrong? If i remvove the condition:
if(I2C_isBusBusy(I2CA_BASE))
and time-out between the reads, it works, if i not time out, the program also gets stuck at
if(I2C_isBusBusy(I2CA_BASE)) in the readData function.
Thanks in advance.
Jan,
F280049 device is running at 100 MHz. I2C when running in standard / fast mode transmits bits at 100 KHz / 400 KHz respectively.
Since your device is running at much much higher rate, you will start running write(sensoreMsg2) before completion of transmission of write(sensoreMsg1). That is the reason why when you include timeout, it works.
Regards,
Manoj
Yes for sure, maybe but my question was not, why does it work with timeouts:
Why "I2C_isBusBusy(I2CA_BASE)" is not preventing from starting my communication, when it is not finished?
Why I2C_isBusBusy(I2CA_BASE) is when i did not start communication, (I tried to protect write access with this function)? When you read under "my idea was", there is the actual thing I am wondering about.
How can I get ride of the I2C_sendStopCondition(I2CA_BASE) condition? How can I prevent reading a new message (without time-out) , when I am still in a read/write process?
Regards and thanks in advance
Jan,
I2CSTR.BB bit tells whether I2C bus is free (or) busy. I2C_isBusBusy(I2CA_BASE) function checks the status of the I2CSTR.BB bit-field. This functions doesn't wait till the I2C bus is free to start another I2C transaction (write / read).
You can keep waiting in an loop until I2C bus is free (or) you can have I2C trigger CPU interrupt when STOP condition is generated. This way you would know that previous I2C transaction is complete and then you can start new I2C transaction.
Regards,
Manoj
Hello,
The singnals look fine to me. Furthermore, I still have the problem, that when I write data to my sensor, the function: I2C_isBusBusy(I2CA_BASE) returns true.
My sensor exspect: start, address, ack(sensor), pointer write address (1 Byte) , ack (sensor), data (1 Byte), ack by Sensor, stop by master. This is done as described in the example in the driverlib:
/ Setup number of bytes to send msgBuffer and address I2C_setDataCount(I2CA_BASE, (msg->numBytes + 1)); // Setup adress of register to write to I2C_putData(I2CA_BASE, msg->pointer); // input data stored to adress for (i = 0; i < msg->numBytes; i++) { I2C_putData( I2CA_BASE, msg->msgBuffer[i] ); } // Send start as master transmitter I2C_setConfig( I2CA_BASE, I2C_MASTER_SEND_MODE ); //send start condition I2C_sendStartCondition( I2CA_BASE ); // send stop condition I2C_sendStopCondition( I2CA_BASE ); errorCode = SUCCESS;
.... ISR:
if(intSource == I2C_INTSRC_STOP_CONDITION) { // // If completed message was writing data, reset msg to inactive state if(currentMsgPtr->msgStatus == MSG_STATUS_WRITE_BUSY) { currentMsgPtr->msgStatus = MSG_STATUS_INACTIVE; // TODO: remove if((I2C_getStatus(I2CA_BASE) & I2C_STS_NO_ACK)) __asm(" ESTOP0"); }
Do you have a guess, why is the bus busy after writing? The NO_ACK flag is not set.
Jan,
After each write / read transaction I would wait till the I2CBus is free as shown below. This way I would always make sure I don't initiate another I2C transaction before previous I2C transaction is complete.
write(sensorMsgs1);
while(I2C_isBusBusy(I2CA_BASE)); //Wait till I2CA bus is free and completes write(sensorMsg1) transaction)
write(sensoreMsg2);
while(I2C_isBusBusy(I2CA_BASE)); //Wait till I2CA bus is free and completes write(sensorMsg1) transaction)
readPcBSensors();
while(I2C_isBusBusy(I2CA_BASE)); //Wait till I2CA bus is free and completes write(sensorMsg1) transaction)
Regards,
Manoj
Hey,
while(I2C_isBusBusy(I2CA_BASE)); won t help.
I found the reason, a stop condtion was not send properly.So if anyone has the same problem that the bus ist busy it may be the stop condition. In this case while(I2C_isBusBusy(I2CA_BASE)); would just loop forever.
But I wonder, why the bus is reporting busy and not via I2C_getStopConditionStatus(I2CA_BASE), is there any reason?
What is still funny, that when I take one device off, that disconnecting one device will mess up the whole communication. Detecting the missing device is no problem, I should just restart the bus afterwards and communication between the devices still connected to the bus should be fine.
What is the best way to reset the bus?
Thanks for your time.
Jan,
What is the status of I2CMDR.STP bit when you see ERROR_BUS_BUSY
failure and not ERROR_STOP_NOT_READY
failure? If STP bit is 0, it just means that there is not pending STOP condition to be generated (or) STP bit was never set to begin with.
When you remove one I2C slave from network, you should see NACK condition when you try to communicate to missing I2C slave. Do you see NACK condition being set? If NACK bit is set, are you making sure to generate STOP condition when you receive NACK condition.
I2C_getStopConditionStatus(I2CA_BASE) function just provides the status of I2CMDR.STP bit.
When I2CMDR.STP = 1, above function returns true '1' meaning there is a pending STOP condition to be generated.
When I2CMDR.STP = 0, above function returns failse '0' meaning there is no pending STOP condition to be generated
What is the best way to reset the bus?
If you I2C bus is stalled, you can always recover the I2C bus by clearing and setting I2C reset bit (I2caRegs.I2CMDR.IRS)
From a driverlib perspective, you can need to disable and enable I2C module as shown below to recover the control of I2C bus and clear error conditions.
I2C_disableModule(I2CA_BASE); //I2CA device held in reset
I2C_enableModule(I2CA_BASE); //I2CA device release from reset
Regards,
Manoj