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 of f28069

Other Parts Discussed in Thread: PCF8575, TMS320F28069

Dear Sir/Madam,

 I am using PCF8575 with TMs320F28069.I want to read the stayus of I/O line of PCF857,.but I am not able to read the PCF8575..I got the data from PCF8575 is 0x4040; and after getting this data my interrupt is halted. I set the I/o line of PCF8575 to 0x0001;I am refering the I2c_eeprom code for interfacing. of PCF8575.


#include"I2C.h"
// Prototype statements for functions found within this file.

int16 ModbusData[MEM_SIZE];
void I2CA_Init(void);

void I2CA_ReadCheck1(Uint8 dido_id);

void I2CA_WriteCheck1(Uint8 dido_id);

Uint16 I2CA_WriteData(struct I2CMSG *msg);
Uint16 I2CA_ReadData(struct I2CMSG *msg);
interrupt void i2c_int1a_isr(void);

struct I2CMSG I2cMsgInOut[8]={
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
								 I2C_SLAVE_DIDO1_ADDR,
                          	 	 I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							 	 I2C_SLAVE_DIDO2_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							  	 I2C_SLAVE_DIDO3_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							     I2C_SLAVE_DIDO4_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
								 I2C_SLAVE_DIDO5_ADDR,
                          	 	 I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							 	 I2C_SLAVE_DIDO6_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							  	 I2C_SLAVE_DIDO7_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_WITHSTOP,
							     I2C_SLAVE_DIDO8_ADDR,
							     I2C_W_NUMBYTES
							  },

						 	};// Msg Byte 1

struct I2CMSG I2cMsgIn[8]={
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
								 I2C_SLAVE_DIDO1_ADDR,
                          	 	 I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							 	 I2C_SLAVE_DIDO2_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							  	 I2C_SLAVE_DIDO3_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							     I2C_SLAVE_DIDO4_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
								 I2C_SLAVE_DIDO5_ADDR,
                          	 	 I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							 	 I2C_SLAVE_DIDO6_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							  	 I2C_SLAVE_DIDO7_ADDR,
							     I2C_W_NUMBYTES
							  },
							  {	 I2C_MSGSTAT_SEND_NOSTOP,
							     I2C_SLAVE_DIDO8_ADDR,
							     I2C_W_NUMBYTES
							  },
					 	};// Msg Byte 1

Uint16 IntSource, i;
Uint16 WriteData = 0xF0;
Uint16 ReadData  = 0;
Uint16 delay_counter = 50000;

void InitI2CGpio();

volatile Uint16 read_data[2];
// Global variables
// Two bytes will be used for the outgoing address,
// thus only setup 14 bytes maximum

struct I2CMSG *CurrentMsgPtr;				// Used in interrupts

void I2CA_Init(void)
{
   unsigned char i;
   // Initialize I2C
   I2caRegs.I2CSAR      = I2C_SLAVE_DIDO6_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
   I2caRegs.I2CCLKH     = 5;			// 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,
   // Clear incoming message buffer
/*   for (i = 0; i < 9; i++)
   {
	   I2cMsgInOut[i].MsgBuffer[0] = WriteData;
	   I2cMsgInOut[i].MsgBuffer[1] = WriteData;
   }
*/
   CurrentMsgPtr = &I2cMsgIn[5];
//   return;
}
void I2CA_WriteCheck1(Uint8 dido_id)
{
	Uint16 Error;
	// Check the outgoing message to see if it should be sent.
	// In this example it is initialized to send with a stop bit.

	if(I2cMsgInOut[dido_id].MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)
	{
	   Error = I2CA_WriteData(&I2cMsgInOut[dido_id]);
	   ModbusData[9]++;
	   ModbusData[3] = I2cMsgInOut[dido_id].MsgStatus;
	   // 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 = &I2cMsgInOut[dido_id];
	      I2cMsgInOut[dido_id].MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
	      ModbusData[18]++;
	      ModbusData[4] = I2cMsgInOut[dido_id].MsgStatus;
	   }
	}  // end of write section
	ModbusData[5]  = I2cMsgInOut[dido_id].SlaveAddress;
	ModbusData[8] = I2cMsgInOut[dido_id].MsgStatus;
}
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)
   {
//	   ModbusData[33]  =  33;
	   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;
   }

   // Setup number of bytes to send
   // MsgBuffer + Address
   I2caRegs.I2CCNT = msg->NumOfBytes;

// 	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;
//   ModbusData[35]  =  35;
   return I2C_SUCCESS;
}
void I2CA_ReadCheck1(Uint8 dido_id)
{
	ModbusData[5]  = I2cMsgIn[dido_id].SlaveAddress;
	ModbusData[8] = I2cMsgIn[dido_id].MsgStatus;
	if(I2cMsgIn[dido_id].MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)
    {
		 // EEPROM address setup portion
	    while(I2CA_ReadData(&I2cMsgIn[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               = &I2cMsgIn[dido_id];
	     I2cMsgIn[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(I2cMsgIn[dido_id].MsgStatus == I2C_MSGSTAT_RESTART)
	  {
	      // Read data portion
		  ModbusData[34]  =  34;
	      while(I2CA_ReadData(&I2cMsgIn[dido_id]) != I2C_SUCCESS)
	      {
	         // Maybe setup an attempt counter to break an infinite while loop
	      }  // Update current message pointer and message status
	      ModbusData[34]              = dido_id;
	      CurrentMsgPtr               = &I2cMsgIn[dido_id];
	      I2cMsgIn[dido_id].MsgStatus = I2C_MSGSTAT_READ_BUSY;
	  }
	  if (I2cMsgIn[dido_id].MsgStatus == I2C_MSGSTAT_INACTIVE)
	  {
		  ModbusData[35]++;
		  I2cMsgIn[dido_id].MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
		  ReadData 	  		  = I2cMsgIn[dido_id].MsgBuffer[0];
		  ReadData 	  		 |= (I2cMsgIn[dido_id].MsgBuffer[1] << 8 );
		  ModbusData[20]      = ReadData;
		  ModbusData[37] = I2cMsgIn[dido_id].MsgStatus;
	 }
	 ModbusData[5] = I2cMsgIn[dido_id].SlaveAddress;
}
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)
   {
	   ModbusData[36]++;
      // Check if bus busy
      if (I2caRegs.I2CSTR.bit.BB == 1)
      {

    	  return I2C_BUS_BUSY_ERROR;
      }
      I2caRegs.I2CCNT 	= 2;
   	  I2caRegs.I2CDXR 	= 0xFF;//msg->MemoryHighAddr;
   	  I2caRegs.I2CDXR 	= 0xFF;//msg->MemoryHighAddr;

      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 = 0x2E20;			// Send restart as master receiver
   }
   ModbusData[15]++;
   return I2C_SUCCESS;
}

interrupt void i2c_int1a_isr(void)     // I2C-A
{
   ModbusData[0]++;

   // 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;
      }
      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[19]++;
            for(i=0; i < 2; i++)
            {
              CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR;
              ModbusData[10+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)
   {
	  ModbusData[39] =  (CurrentMsgPtr->MsgStatus);
	  ModbusData[38]++;
      if(I2caRegs.I2CSTR.bit.NACK == 1)
      {
         I2caRegs.I2CMDR.bit.STP = 1;
         I2caRegs.I2CSTR.all	 = I2C_CLR_NACK_BIT;
      }
      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.
//===========================================================================
8228.I2C.h

Please find the attached file for your reference.

Please help me its urgent.

  • Hello,
    What data do you want to send to your device?
    I didn't find your data for MsgBuffer that defined as I2CMSG. You only mentioned MsgStatus, Slave Address, and NumOfBytes in your I2cMsgInOut[].

    // I2C Message Structure
    struct I2CMSG {
      Uint16 MsgStatus;                // Word stating what state msg is in:
                                      //   I2C_MSGCMD_INACTIVE = do not send msg
                                      //   I2C_MSGCMD_BUSY = msg start has been sent,
                                      //                     awaiting stop
                                      //   I2C_MSGCMD_SEND_WITHSTOP = command to send
                                      //       master trans msg complete with a stop bit
                                      //   I2C_MSGCMD_SEND_NOSTOP = command to send
                                      //       master trans msg without the stop bit
                                      //   I2C_MSGCMD_RESTART = command to send a restart
                                      //       as a master receiver with a stop bit
      Uint16 SlaveAddress;            // I2C address of slave msg is intended for
      Uint16 NumOfBytes;            // Num of valid bytes in (or to be put in MsgBuffer)
      Uint16 MemoryHighAddr;        // EEPROM address of data associated with msg (high byte)
      Uint16 MemoryLowAddr;            // EEPROM address of data associated with msg (low byte)
      Uint16 MsgBuffer[I2C_MAX_BUFFER_SIZE];// Array holding msg data - max that
                          // MAX_BUFFER_SIZE can be is 16 due to
                          // the FIFO's
    };


    Also you don't need to send address for reading function, based on your device datasheet.

    So delete these lines on your I2CA_ReadData():
       I2caRegs.I2CCNT     = 2;
       I2caRegs.I2CDXR     = 0xFF;//msg->MemoryHighAddr;
       I2caRegs.I2CDXR     = 0xFF;//msg->MemoryHighAddr;

       I2caRegs.I2CMDR.all   = 0x2620;            // Send data to setup EEPROM address


    Best regards,
    Maria

  • Hello,

    Thanks for the reply.

    I want to perform read operation.

    As per the datasheet of PCF8575 after sending address to read the status of I/O pins they must be  configured as Input.By sending 0xFF they will be configured as Input.

    So I send first slave Add,then send 0xff & 0xff and generate Restart & try to read from Slave.But I get 0x40 , 0x3D 0x7E.

  • sagar yadav said:
    As per the datasheet of PCF8575 after sending address to read the status of I/O pins they must be  configured as Input.By sending 0xFF they will be configured as Input.

    I am not sure about this.

    The datasheet mentions:

    Before reading from the PCF8575, all ports desired as input should be set to logic 1. To read from the ports
    (input mode), the master first addresses the slave device, setting the last bit of the byte containing the slave
    address to logic 1. The data bytes that follow on the SDA are the values on the ports. If the data on the input
    port changes faster than the master can read, this data may be lost.


    However, it does not mention how to set the ports to logic 1 because SDA only contains slave address + Read bit + data (no port logic), like mentioned in the diagram (see the content of SDA).

    So you can try to follow this SDA content.

    Best regards,

    Maria