I2C example

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello everyone;

   

I need to connect two PSoC's with I2C communication protocol. So i have CY8C29466 for master and CY8C28000 for slave. I used I2CHW single master and slave operations and wrote these codes;

   

For Master;

   

//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

   

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

   


 
/* Define slave address */
#define SLAVE_ADDRESS 0x1
/* Define buffer size */
#define BUFFER_SIZE 0x08
/* Setup buffers */
BYTE txBuffer[BUFFER_SIZE];
BYTE rxBuffer[BUFFER_SIZE];
BYTE status;
BYTE x;
void main(void)
{
/* Start the master */
I2CHW_Start();
I2CHW_EnableMstr();
/* Enable the global and local interrupts */
M8C_EnableGInt;
I2CHW_EnableInt();
/* Send and Receive forever*/
while( 1 )
{
/* Send the contents of the data in txBuffer */;
I2CHW_bWriteBytes(SLAVE_ADDRESS, txBuffer, BUFFER_SIZE, I2CHW_CompleteXfer);
/* Wait until the data is transferred */
while(!(I2CHW_bReadI2CStatus() & I2CHW_WR_COMPLETE));
/* Clear Write Complete Status bit */
I2CHW_ClrWrStatus();
/* Read from the slave and place in rxBuffer */;
I2CHW_fReadBytes(SLAVE_ADDRESS, rxBuffer, BUFFER_SIZE, I2CHW_CompleteXfer);
/* Wait until the data is read */
while(!(I2CHW_bReadI2CStatus() & I2CHW_RD_COMPLETE));

   

/* Clear Read Complete Status bit */
I2CHW_ClrRdStatus();
/* Increment 1st byte in txBuffer so the data changes each loop */
txBuffer[0]++;

   


}
}

   

For Slave;

   

//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

   

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

   


/* Define buffer size */
#define BUFFERSIZE 8
/* Setup a 8 byte buffer */
BYTE txRxBuffer[BUFFERSIZE];
BYTE status;

   

void main(void)
{
/* Start the slave and wait for the master */
I2CHW_Start();
I2CHW_EnableSlave();
/* Enable the global and local interrupts */
M8C_EnableGInt;
I2CHW_EnableInt();
/* Setup the Read and Write Buffer - set to the same buffer */
I2CHW_InitRamRead(txRxBuffer,BUFFERSIZE);
I2CHW_InitWrite(txRxBuffer,BUFFERSIZE);
/* Echo forever */
while( 1 )
{
status = I2CHW_bReadI2CStatus();
/* Wait to read data from the master */
if( status & I2CHW_WR_COMPLETE )
{
/* Data received - clear the Write status */
I2CHW_ClrWrStatus();
/* Reset the pointer for the next read data */
I2CHW_InitWrite(txRxBuffer,BUFFERSIZE);
}
/* wait until data is echoed */
if( status & I2CHW_RD_COMPLETE )
{
/* Data echoed - clear the read status */
I2CHW_ClrRdStatus();
/* Reset the pointer for the next data to echo */
I2CHW_InitRamRead(txRxBuffer,BUFFERSIZE);
}
}
} //end of main

   

But i don't know what to do next. If somebody can show me any example for these project i can handle with. Let's assume i have an integer value in slave (int x=10;) and i want to show that on master's LCD. How can i get this value and save on integer in master? If anybody can tell me i will be appreciate..

   

Thanks..

0 Likes
5 Replies
Anonymous
Not applicable

Are you able to establish a Master-Slave comm?

   

Once your communication is set up then data trasnfer can be easy.

   

Regards,

   

Girish

0 Likes
Anonymous
Not applicable

Try the below code,

   

 

   

   

// Slave Code

   

// User module to use: EzI2C

   

// Set slave address to 0x04

   

 

   

#include <m8c.h>        // part specific constants and macros

   

#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

   

 

   

struct I2C_Regs  

   

{   

   

WORD wDATA;

   

} MyI2C_Regs; 

   

 

   

void main(void)

   

{

   

M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts

   

   

EzI2Cs_SetRamBuffer(1,1,(BYTE *)&MyI2C_Regs);  

   

EzI2Cs_Start(); 

   

   

while(1)

   

{

   

// Copying 0x99AA for master to read

   

MyI2C_Regs.wDATA = 0x99AA; 

   

}

   

}

   

 

   

 

   

// Master Code

   

// User Module to use I2Cm

   

#include <m8c.h>        // part specific constants and macros

   

#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

   

 

   

void main(void)

   

{

   

BYTE bData1;

   

BYTE bData2;

   

WORD wData;

   

   

M8C_EnableGInt;

   

 

   

   

I2Cm_Start();

   

   

// Set the base pointer

   

I2Cm_fSendStart(0x04,I2Cm_WRITE); // Do a write

   

I2Cm_fWrite(0x00); // Set BP

   

I2Cm_SendStop();

   

   

I2Cm_fSendStart(0x04,I2Cm_READ); // Do a write

   

bData1 = I2Cm_bRead(I2Cm_ACKslave)

   

bData2 = I2Cm_bRead(I2Cm_ACKslave)

   

I2Cm_SendStop();

   

wData = (bData1 << 😎 || (bData2)

   

   

//Display wData to LCD wData will contain 0x99AA

   

   

}

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I'll try to explain how I2C works, maybe that hels you to get further.

   

The slave (it has an address in the range (0 to 0x7f) is not able to send or read data itself (!!!)  instead it opens up a memory area from wherte the master may read or write into. For both the buffers (read from and write to) to organize there are two APIs: Slave_InitReadBuf() and Slave_InitWriteBuf(). The software maintains counters, so that a master cannot read behind the buffer-size or even write behind the buffer wich would otherwise corrupt data on the slave.

   

Thats all.

   

The consequences, not quite obvious, are: The slave must always be ready to serve its master. when from a buffer all data is read, the slave must immediately set up a buffer again. Same of course for a buffer written to. So the slave has to poll for a complete transfer always.

   

Hope thatr helps.

   

Bob

0 Likes
Anonymous
Not applicable

I've implemented an I2C project wherein a certain value is written by the Master at the end of the buffer that acts as a flag to signify that all data was transmitted to the slave. At that point the slave can then process the data. After it finished processing the data, the slave then makes available in the buffer any data that might be needed by the master. Appropriate flag values are written at the end of the buffer to indicate that the the data was processed by the slave or the slave is waiting for the master to retrieve available data.

   

MASTER:

   

struct DataBuffer {
    BYTE SubAddr; 
    BYTE rxData[64];
    BYTE Flag;
    BYTE txData[64];
    BYTE ChkSum;
    BYTE Request;
} Buffer, rxBuffer; 

....

   

      if (rxBuffer.Flag>0 && rxBuffer.Flag<0xFF) {
        // assume that if flag is set between 1-0xFE, slave is sending data
        // process slave data here
        
        // Reset flag value to 0x00 to inform the slave that the data was successfully read
        // Set flag value to, for example, 0xFF if sending command/data to slave
        rxBuffer.Flag=0;
        I2C_Mstatus = I2Cm_bWriteBytes(Slave_address, (BYTE *)&rxBuffer, sizeof(rxBuffer.rxData)+2, I2Cm_CompleteXfer);
      }

   

 

   

SLAVE:

   

/* Start the I2C slave */ 
    //void EzI2Cs_SetRamBuffer(BYTE bSize, BYTE bRWboundry, (BYTE *)pAddr); 
    //BYTE bSize: Size of the data structure exposed to an I2C master. The minimum value for bSize is 1 and the maximum is 255.
    //BYTE bRWboundry: The size of the writable locations starting with the first location. This value should always be less than or equal to bSize for proper operation.
    EzI2Cs_SetRamBuffer(sizeof(Buffer)-1, sizeof(Buffer.rxData)+1, (BYTE *) &Buffer.rxData); 
    EzI2Cs_Start();

    EzI2Cs_SetAddr(ConfigAddr);     // Change address to ...
   
       while (1) {
        I2C_Sstatus|=EzI2Cs_GetActivity();

        if (Buffer.Flag==0xFF) {
            // command was sent by master... process data here
            // set Buffer.Flag to 0x00 to signify command was executed and slave is ready for new command
            // Buffer.rxData contains info from master
        }
   
        if (Buffer.Flag==0x00 && mustReplytoMaster) {
            // need to send data to master
            // fill up the buffer and then set Buffer.Flag to a unique value <>0x00 or 0xFF to signify data is ready to be read
            // Buffer.txData contains info coming from slave, being sent to master
        }
   
    }

0 Likes
Anonymous
Not applicable

Some lines were omitted while pasting the code. It should be:

   

MASTER:

struct DataBuffer {
    BYTE SubAddr;
    BYTE rxData[64];
    BYTE Flag;
    BYTE txData[64];
    BYTE ChkSum;
    BYTE Request;
} Buffer, rxBuffer;

....
while (1) {

   

.....
      rxBuffer.Flag=0;
      I2C_Mstatus = I2Cm_fReadBytes(MotherBoard,(BYTE *)&rxBuffer.rxData, sizeof(rxBuffer)-1, I2Cm_RepStart);
     
      if (rxBuffer.Flag>0 && rxBuffer.Flag<0xFF) {
        // assume that if flag is set between 1-0xFE, slave is sending data
        // process slave data here
       
        // Reset flag value to 0x00 to inform the slave that the data was successfully read
        // Set flag value to, for example, 0xFF if sending command/data to slave
        rxBuffer.Flag=0;
        I2C_Mstatus = I2Cm_bWriteBytes(Slave_address, (BYTE *)&rxBuffer, sizeof(rxBuffer.rxData)+2, I2Cm_CompleteXfer);
      }
}
 

SLAVE:

/* Start the I2C slave */
    //void EzI2Cs_SetRamBuffer(BYTE bSize, BYTE bRWboundry, (BYTE *)pAddr);
    //BYTE bSize: Size of the data structure exposed to an I2C master. The minimum value for bSize is 1 and the maximum is 255.
    //BYTE bRWboundry: The size of the writable locations starting with the first location. This value should always be less than or equal to bSize for proper operation.
    EzI2Cs_SetRamBuffer(sizeof(Buffer)-1, sizeof(Buffer.rxData)+1, (BYTE *) &Buffer.rxData);
    EzI2Cs_Start();

    EzI2Cs_SetAddr(ConfigAddr);     // Change address to ...
  
       while (1) {
        I2C_Sstatus|=EzI2Cs_GetActivity();

        if (Buffer.Flag==0xFF) {
            // command was sent by master... process data here
            // set Buffer.Flag to 0x00 to signify command was executed and slave is ready for new command
            // Buffer.rxData contains info from master
        }
  
        if (Buffer.Flag==0x00 && mustReplytoMaster) {
            // need to send data to master
            // fill up the buffer and then set Buffer.Flag to a unique value <>0x00 or 0xFF to signify data is ready to be read
            // Buffer.txData contains info coming from slave, being sent to master
        }
  
    }   

0 Likes