PSoc as I2C Master and ST as I2C Slave

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

cross mob
user_2581831
Level 2
Level 2
10 sign-ins 5 questions asked First solution authored

Hi,

I want to implement I2C communication between PSOC and ST.

I've configured PSoc as I2C Master and ST as I2C Slave. I've succesfully transferred data from PSoc to ST but I'couldn't read data from ST.

Here's the details about my implemention.

When I use I2C_Write_Data function on PSoc side, I didn't encounter a problem about the data transmission to ST from PSoC

I'didnt implement I2C Slave on ST side before. I may have used wrong APIs or made some configuration mistakes.

I've attached the images about the implementation. (Codes and Configuration). I'll be appreciated if you illuminate me about this problem. This is my second post on this web site so that please ignore my faults about this topic that I have )

Have a nice day..

1- ST I2C Slave Code

ST_I2C_Code.PNG

2- St CubeMx I2C Slave Configuration

ST_CubeMx_I2C_Conf.PNG

3- Cypress I2C Master Functions

Cypress_I2C_Code.PNG

4- Cypress I2C Configuration

Cypress_I2C_Conf.PNG

0 Likes
1 Solution
user_2581831
Level 2
Level 2
10 sign-ins 5 questions asked First solution authored

Hi,

I've solved the problem by increasing the timeout values of I2C functions both on PSoC and ST side and changing I2CM_I2C_ACK_DATA to I2CM_I2C_NAK_DATA on PSoC side..I've updated the timeout values as 0xFF instead of 200 on both side. and I've set up the data rate of  communication  as 400khz as fast mode. Here's the functions that I have used for proper operation.

//PSoC I2C Master //

//Functions and Definitions//

#define I2C_TIMEOUT 0xFF

#define SLAVE_ADDR 0x43

void I2C_Write_Data(uint8_t Slave_Address, uint8_t I2C_Data)

{

     I2CM_I2CMasterSendStart(Slave_Address, I2CM_I2C_WRITE_XFER_MODE,I2C_TIMEOUT);

     I2CM_I2CMasterWriteByte(I2C_Data, I2C_TIMEOUT);

     I2CM_I2CMasterSendStop(I2C_TIMEOUT);

}

uint8_t I2C_Read_Data(uint8_t Slave_Address)

{

     uint8_t I2C_BUFFER = 0;

     I2CM_I2CMasterSendStart(Slave_Address, I2CM_I2C_READ_XFER_MODE,I2C_TIMEOUT);

     I2CM_I2CMasterReadByte(I2CM_I2C_NAK_DATA, &I2C_BUFFER, I2C_TIMEOUT);

     I2CM_I2CMasterSendStop(I2C_TIMEOUT);

     return I2C_BUFFER;

}

//Main_Function//

I2C_Write_Data(SLAVE_ADDR, 0xA0);

uint8_t I2C_RECEIVE_BUF = I2C_Read_Data(SLAVE_ADDR); // Returns the same data that's sent to the ST Slave. 0xA0.

//ST I2C Slave - Main Function//

uint8_t I2C_BUFFER = 0;

while(HAL_I2C_GetState(&hi2cs) != HAL_I2C_STATE_READY);

HAL_I2C_Slave_Receive(&hi2cs, &I2C_BUFFER, 1, HAL_MAX_DELAY);

switch(I2C_BUFFER)

{

     case 0xA0:

          uint8_t I2C_TRANSMIT_BUFFER = 0xA0;

          HAL_I2C_Slave_Transmit(&hi2cs, &I2C_TRANSMIT_BUFFER,1,HAL_MAX_DELAY);

     break;

}

View solution in original post

0 Likes
3 Replies
lock attach
Attachments are accessible only for community members.
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi,

Can you please follow the recommended firmware flow for I2C_Write and I2C_Read from PSoC?

uint8 WriteCommandPacket(uint8 command)

{

    uint8 errorStatus = 0;

    uint8 status = TRANSFER_ERROR;

   

    /* Create packet to send to slave */

    CreateCommandPacketBuffer(command);

   

    /* Send start condition */

    if(0u == mI2C_I2CMasterSendStart(I2C_SLAVE_ADDR, mI2C_I2C_WRITE_XFER_MODE, I2C_TIMEOUT))

    { 

        /* Write bytes from the write buffer to the Slave */

        uint8 cnt = 0;

        do

        {

            /* Write byte and recieve ACK/NACK */

            errorStatus = mI2C_I2CMasterWriteByte(buffer[cnt], I2C_TIMEOUT);

            ++cnt;

        }   

        while((errorStatus == mI2C_I2C_MSTR_NO_ERROR) && (cnt < WR_BUFFER_SIZE));

    }

   

    /* Transfer succeeds send stop and return Success */

    if((errorStatus == mI2C_I2C_MSTR_NO_ERROR)      ||

       (errorStatus == mI2C_I2C_MASTER_CMD_M_NACK))

    {

        if(mI2C_I2CMasterSendStop(I2C_TIMEOUT) == mI2C_I2C_MSTR_NO_ERROR)

        {

            status = TRANSFER_CMPLT;

        }

    }

   

    return(status);

}   

static uint8 ReadStatusPacket(void)

{  

    uint8 errorStatus;

    uint8 status = TRANSFER_ERROR;

   

    /* Send start condition and store read bytes in rdBuffer[] until end of buffer is reached */

    errorStatus = mI2C_I2CMasterSendStart(I2C_SLAVE_ADDR, mI2C_I2C_READ_XFER_MODE, I2C_TIMEOUT);

    if(errorStatus == mI2C_I2C_MSTR_NO_ERROR)

    {

        uint8 cnt = 0;

        uint8 cmd = mI2C_I2C_ACK_DATA;

       

        do

        {

            if (cnt == (RD_BUFFER_SIZE - 1U))

            {

                /* Send NACK on last byte */

                cmd = mI2C_I2C_NAK_DATA;

            }

            /* Read data from slave and store in rdBuffer[] */

            errorStatus = mI2C_I2CMasterReadByte(cmd, rdBuffer + cnt, I2C_TIMEOUT);

            ++cnt;

        }

        while ((errorStatus == mI2C_I2C_MSTR_NO_ERROR) && (cnt < RD_BUFFER_SIZE));

    }

   

    /* If read succeeds, send stop condition and return success */

    if ((errorStatus == mI2C_I2C_MSTR_NO_ERROR)     ||

        (errorStatus == mI2C_I2C_MASTER_CMD_M_NACK))

    {

        if (mI2C_I2CMasterSendStop(I2C_TIMEOUT) == mI2C_I2C_MSTR_NO_ERROR)

        {

            /* Check that data read from the slave is correct */

            if ((BUFFER_SOP == rdBuffer[RD_BUFFER_SOP_POS]) &&

                (BUFFER_EOP == rdBuffer[RD_BUFFER_EOP_POS]) &&

                (STS_CMD_DONE == rdBuffer[RD_BUFFER_STS_POS]))

            {

                status = TRANSFER_CMPLT;

            }

        }   

    }

    return(status);

}

The above code is taken from the attached I2C_Master Low level code example. Please refer it once.

Also, please create the post in ST's Forum also so that you can get support from their community also

Thanks

Ganesh

0 Likes

Hi,

Thanks for replying my question, but I've tried the example I2C project on the attachment and it didn't work for me. I think there's some kind of synchronization problem occuring between master and slave device when reading data from slave device on master side. I still couldn't figure out how to solve problem.

Have a nice day.

Thanks.

0 Likes
user_2581831
Level 2
Level 2
10 sign-ins 5 questions asked First solution authored

Hi,

I've solved the problem by increasing the timeout values of I2C functions both on PSoC and ST side and changing I2CM_I2C_ACK_DATA to I2CM_I2C_NAK_DATA on PSoC side..I've updated the timeout values as 0xFF instead of 200 on both side. and I've set up the data rate of  communication  as 400khz as fast mode. Here's the functions that I have used for proper operation.

//PSoC I2C Master //

//Functions and Definitions//

#define I2C_TIMEOUT 0xFF

#define SLAVE_ADDR 0x43

void I2C_Write_Data(uint8_t Slave_Address, uint8_t I2C_Data)

{

     I2CM_I2CMasterSendStart(Slave_Address, I2CM_I2C_WRITE_XFER_MODE,I2C_TIMEOUT);

     I2CM_I2CMasterWriteByte(I2C_Data, I2C_TIMEOUT);

     I2CM_I2CMasterSendStop(I2C_TIMEOUT);

}

uint8_t I2C_Read_Data(uint8_t Slave_Address)

{

     uint8_t I2C_BUFFER = 0;

     I2CM_I2CMasterSendStart(Slave_Address, I2CM_I2C_READ_XFER_MODE,I2C_TIMEOUT);

     I2CM_I2CMasterReadByte(I2CM_I2C_NAK_DATA, &I2C_BUFFER, I2C_TIMEOUT);

     I2CM_I2CMasterSendStop(I2C_TIMEOUT);

     return I2C_BUFFER;

}

//Main_Function//

I2C_Write_Data(SLAVE_ADDR, 0xA0);

uint8_t I2C_RECEIVE_BUF = I2C_Read_Data(SLAVE_ADDR); // Returns the same data that's sent to the ST Slave. 0xA0.

//ST I2C Slave - Main Function//

uint8_t I2C_BUFFER = 0;

while(HAL_I2C_GetState(&hi2cs) != HAL_I2C_STATE_READY);

HAL_I2C_Slave_Receive(&hi2cs, &I2C_BUFFER, 1, HAL_MAX_DELAY);

switch(I2C_BUFFER)

{

     case 0xA0:

          uint8_t I2C_TRANSMIT_BUFFER = 0xA0;

          HAL_I2C_Slave_Transmit(&hi2cs, &I2C_TRANSMIT_BUFFER,1,HAL_MAX_DELAY);

     break;

}

0 Likes