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.

I2c problem while continue Read and write operation with F28069

Other Parts Discussed in Thread: PCF8575

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.

1172.I2C.c

#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.
//===========================================================================
7585.main.c
{
   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.
//===========================================================================
2100.APP.c
						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;
	
2235.I2C.h