Hi,
I am using F28069 Micro controller for my application.I am interfacing 3 slave i.e. PCF8575 I am getting the problem while doing continue read and write operation.I am able to do individual Read and write operation.Please find attached source and header file of i2c. I am using 4.7 K Pull up resister for SDA and SCL.
While debugging I found that it is stuck at following instruction.
// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1)
{
return (I2C_BUS_BUSY_ERROR);
}
Waiting for reply.
#include"I2C.h" // Prototype statements for functions found within this file. // Note: I2C Macros used in this example can be found in the // F2806x_I2C_defines.h file // Prototype statements for functions found within this file. Uint8 volatile write_done = 0; Uint8 volatile read_done = 0; void I2CA_Init(void); Uint16 I2CA_WriteData(struct I2CMSG *msg); Uint16 I2CA_ReadData(struct I2CMSG *msg); interrupt void i2c_int1a_isr(void); void Read_Data(Uint8 dido_id); void Write_Data(Uint8 dido_id); struct I2CMSG I2cMsgOut1[8]={ { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO1_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO2_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO3_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO4_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO5_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO6_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO7_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, { I2C_MSGSTAT_SEND_WITHSTOP, I2C_SLAVE_DIDO8_ADDR, I2C_W_NUMBYTES, I2C_EEPROM_HIGH_ADDR1, I2C_EEPROM_LOW_ADDR1 }, };// Msg Byte 1 struct I2CMSG I2cMsgIn1[8]={ { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO1_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO2_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO3_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO4_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO5_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO6_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO7_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, { I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_DIDO8_ADDR, I2C_R_NUMBYTES, I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR }, };// Msg Byte 1 struct I2CMSG *CurrentMsgPtr; // Used in interrupts Uint16 Error; void I2CA_Init(void) { // Initialize I2C I2caRegs.I2CSAR = I2C_SLAVE_DIDO1_ADDR; // Slave address - EEPROM control code I2caRegs.I2CPSC.all = 6; // Prescaler - need 7-12 Mhz on module clk // I2caRegs.I2CCLKL = 10; // NOTE: must be non zero //400k // I2caRegs.I2CCLKH = 5; // NOTE: must be non zero I2caRegs.I2CCLKL = 75; // NOTE: must be non zero //100k I2caRegs.I2CCLKH = 30; // NOTE: must be non zero I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset // Stop I2C when suspended I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT, } void Write_Data(Uint8 dido_id) { // Check the outgoing message to see if it should be sent. // In this example it is initialized to send with a stop bit. if(I2cMsgOut1[dido_id].MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP) { Error = I2CA_WriteData(&I2cMsgOut1[dido_id]); // If communication is correctly initiated, set msg status to busy // and update CurrentMsgPtr for the interrupt service routine. // Otherwise, do nothing and try again next loop. Once message is // initiated, the I2C interrupts will handle the rest. Search for // i2c_int1a_isr in this file. if (Error == I2C_SUCCESS) { CurrentMsgPtr = &I2cMsgOut1[dido_id]; I2cMsgOut1[dido_id].MsgStatus = I2C_MSGSTAT_WRITE_BUSY; } else { I2cMsgOut1[dido_id].MsgStatus = I2C_MSGSTAT_SEND_WITHSTOP; } } }// end of write section void Read_Data(Uint8 dido_id) { if(I2cMsgIn1[dido_id].MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) { // EEPROM address setup portion while(I2CA_ReadData(&I2cMsgIn1[dido_id]) != I2C_SUCCESS) { // Maybe setup an attempt counter to break an infinite while // loop. The EEPROM will send back a NACK while it is performing // a write operation. Even though the write communique is // complete at this point, the EEPROM could still be busy // programming the data. Therefore, multiple attempts are // necessary. } // Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1[dido_id]; I2cMsgIn1[dido_id].MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY; } // Once message has progressed past setting up the internal address // of the EEPROM, send a restart to read the data bytes from the // EEPROM. Complete the communique with a stop bit. MsgStatus is // updated in the interrupt service routine. else if(I2cMsgIn1[dido_id].MsgStatus == I2C_MSGSTAT_RESTART) { // Read data portion while(I2CA_ReadData(&I2cMsgIn1[dido_id]) != I2C_SUCCESS) { // Maybe setup an attempt counter to break an infinite while // loop. } // Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1[dido_id]; I2cMsgIn1[dido_id].MsgStatus = I2C_MSGSTAT_READ_BUSY; } else if(I2cMsgIn1[dido_id].MsgStatus == I2C_MSGSTAT_INACTIVE) { read_done = 1; if(write_read == 0) //For Read Operation { I2cMsgIn1[i2c1_io_di_id].MsgStatus = I2C_MSGSTAT_SEND_NOSTOP; } switch(dido_id) { case DI_0 : di_0.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_1 : di_1.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_2 : di_2.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_3 : di_3.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_4 : di_4.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_5 : di_5.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_6 : di_6.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; case DI_7 : di_7.all = ( ModbusData[DI_READ_LOW] | (ModbusData[DI_READ_HIGH] << 8)); break; default : break; } } }// end of read section Uint16 I2CA_WriteData(struct I2CMSG *msg) { Uint16 i; // 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 = msg->SlaveAddress; // Check if bus busy if (I2caRegs.I2CSTR.bit.BB == 1) { return (I2C_BUS_BUSY_ERROR); } I2caRegs.I2CCNT = msg->NumOfBytes; /* I2caRegs.I2CCNT = msg->NumOfBytes+2; // Setup data to send I2caRegs.I2CDXR = msg->MemoryHighAddr; I2caRegs.I2CDXR = msg->MemoryLowAddr; */ // for (i=0; i<msg->NumOfBytes-2; i++) for (i=0; i<msg->NumOfBytes; i++) { I2caRegs.I2CDXR = *(msg->MsgBuffer+i); } // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20; return I2C_SUCCESS; } Uint16 I2CA_ReadData(struct I2CMSG *msg) { // 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; } I2caRegs.I2CSAR = msg->SlaveAddress; if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) { // Check if bus busy if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } I2caRegs.I2CCNT = 2; I2caRegs.I2CDXR = msg->MemoryHighAddr; I2caRegs.I2CDXR = msg->MemoryLowAddr; I2caRegs.I2CMDR.all = 0x2620; // Send data to setup EEPROM address } else if(msg->MsgStatus == I2C_MSGSTAT_RESTART) { I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver } return I2C_SUCCESS; } interrupt void i2c_int1a_isr(void) // I2C-A { Uint16 IntSource, i; // Read interrupt source IntSource = I2caRegs.I2CISRC.all; // Interrupt source = stop condition detected if(IntSource == I2C_SCD_ISRC) { // If completed message was writing data, reset msg to inactive state if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE; if(read_flag == 1) { write_read = 0; //Start Read Opeartion read_done = 0; } write_done = 1; } else { // If a message receives a NACK during the address setup portion of the // EEPROM read, the code further below included in the register access ready // interrupt source code will generate a stop condition. After the stop // condition is received (here), set the message status to try again. // User may want to limit the number of retries before generating an error. if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP; } // If completed message was reading EEPROM data, reset msg to inactive state // and read data from FIFO. else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE; ModbusData[92]++; for(i=0; i < I2C_R_NUMBYTES; i++) { CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR; ModbusData[DI_READ_LOW+i] = I2caRegs.I2CDRR; } } } } // end of stop condition detected // Interrupt source = Register Access Ready // This interrupt is used to determine when the EEPROM address setup portion of the // read data communication is complete. Since no stop bit is commanded, this flag // tells us when the message has been sent instead of the SCD flag. If a NACK is // received, clear the NACK bit and command a stop. Otherwise, move on to the read // data portion of the communication. else if(IntSource == I2C_ARDY_ISRC) { if(I2caRegs.I2CSTR.bit.NACK == 1) { I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; } else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART; } } // end of register access ready else { // Generate some error due to invalid interrupt source asm(" ESTOP0"); } // Enable future I2C (PIE Group 8) interrupts PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; } //=========================================================================== // No more. //===========================================================================
{ for(;;) { switch(write_read) { case WRITE : // write_done = 0; if(read_done == 1) { Write_Data(i2c1_io_do_id); } break; case READ : if(write_done == 1) { ModbusData[94]++; Read_Data(i2c1_io_di_id); } break; default : break; } } // end of for(;;) } // end of main //=========================================================================== // No more. //===========================================================================
I2cMsgOut1[DO_1].MsgBuffer[0] = ( data & 0x00FF); I2cMsgOut1[DO_1].MsgBuffer[1] = ( data >> 8); i2c1_io_do_id = DO_1; if(I2cMsgOut1[DO_1].MsgStatus == I2C_MSGSTAT_INACTIVE) { I2cMsgOut1[DO_1].MsgStatus = I2C_MSGSTAT_SEND_WITHSTOP; } I2cMsgIn1[i2c1_io_di_id].MsgStatus = I2C_MSGSTAT_INACTIVE; write_read = 1; write_done = 0; read_flag = 0;