Help with I2C Slave Write?

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

cross mob
joli_601446
Level 5
Level 5
10 likes given 10 sign-ins 5 sign-ins

Hello, I'm looking for some example code on I2C Slave write to an I2C Master. I found an example:

https://community.cypress.com/thread/34177?q=Help%20with%20I2C%20Slave%20Write

But the example project is not complete when I loaded it into PSOC Creator.

I was looking at the EZI2C datasheet and the I2C Master/Mulit-Master/Save documents and I don't see a function that the Slave would use to write to a buffer to be send back to a Slave. If anyone has some example code or any helpful comments please let me know

Respectfully,

Joe

0 Likes
1 Solution

The master is not "only a doing a read on a Slave buffer". Your code starts with a I2CM_MasterWriteBuf(). Read and understand my previous post which explains why slavebuff[1] was changed.

Bob

View solution in original post

0 Likes
16 Replies
joli_601446
Level 5
Level 5
10 likes given 10 sign-ins 5 sign-ins

I'm using the PSOC5 CY8CKIT-059 kit.

0 Likes
RyanZhao
Moderator
Moderator
Moderator
250 sign-ins First question asked 750 replies posted

Hi Joe,

Could you double-check if EZI2CDesign code example in PSoC Creator can help you or not?

Thanks,

Ryan

0 Likes
lock attach
Attachments are accessible only for community members.

An I2C slave cannot write to a master, only a master can read and write to a slave.

Bob

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

HI, you are absolutely correct. I should say I'm looking for an example where the Master reads from the Slave. I trying to do an example where I have one I2C Slave running on a PSoc5 Target only and one I2C Master running on another PSoc5 Target only. I have the Master to do one read from the Slave. I run the Master but the Slave doesn't respond. Can you look over the short example projects and see I am doing things right?

MasterRead.jpg

Thanks

Joe

0 Likes

Byte I2C interface is quite simple: After setting up the component and starting it you use

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWriteByte(Register);                // Indicate which register you want to write to

    I2C_MasterWriteByte(Value);                // Write to register

    I2C_MasterSendStop();                    // End of transaction

When you want to read from a device you use (example for reading two bytes

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWrite(Register);                // Indicate which register you want to write to

    I2C_MasterSendRestart(DeviceAddress,I2C_READ_XFER_MODE);

    I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register

    I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed

    I2C_MasterSendStop();                    // End of transaction

Not too difficult. Keep in mind that most of the APIs (except those for reading a byte) return a status byte which, when non-zero indicate an error condition.

The high-level APIs must be used in this way:

Writing to slave Count bytes

I2C_MasterWriteBuf(SlaveAddress,DataPtr,Count,I2C_MODE_COMPLETE_XFER);

Reading from Slave sending register/command byte first:

I2C_MasterWriteBuf(SlaveAddress,&RegAddress,1,I2C_MODE_NO_STOP);

I2C_MasterReadBuf(SlaveAddress,DataPtr,Count,I2C_MODE_REPEAT_START);

Bob

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

HI, what do I enter for I2C_ACK_DATA or I2C_NAK_DATA? I'm using the I2C example you created a while back. I thought I could add in a MasterRead call to help understand to it is done.

Thanks,

Joe

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

At the end of the day I got something working. I could not get the "simple" method or the high-level API working. I did get working the example found on page 37 and 38 on the Master/Multi-Master/Slave document. I have three methods that I can try in the code. Can you look at the first two option:

test = 1;
if(test == 1 )  // simple way, this one is not working
{
Master_I2C_MasterSendStart(SlaveAddr,Master_I2C_WRITE_XFER_MODE);// Initialize a transaction for writing
Master_I2C_MasterWriteByte(mydata);                                    // Indicate which register you want to write to
Master_I2C_MasterSendRestart(SlaveAddr,Master_I2C_READ_XFER_MODE);
Master_I2C_MasterReadByte(Master_I2C_ACK_DATA);                // Read from register
Master_I2C_MasterReadByte(Master_I2C_NAK_DATA);                // Read from register, last byte is NAKed
Master_I2C_MasterSendStop();                                   // End of transaction
temp++;
}
else if(test == 2) // high-leve API way "Automatic", not working
{  
Master_I2C_MasterWriteBuf(SlaveAddr,  &mydata,1,Master_I2C_MODE_NO_STOP);
Master_I2C_MasterReadBuf(SlaveAddr,RdMasterBuffer,1,Master_I2C_MODE_REPEAT_START);
}
0 Likes

In your code I cannot see the result of any I2C functions.

Please: Set optimization to "none"

Save and inspect in debug mode all results of I2C functions for != zero

Bob

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

HI, I'm making processing. Here is my code:

   Master_I2C_MasterSendStart(SlaveAddr,Master_I2C_WRITE_XFER_MODE);// Initialize a transaction for writing
   Master_I2C_MasterWriteByte(2);                                 // Indicate which register you want to write to
   Master_I2C_MasterSendRestart(SlaveAddr,Master_I2C_READ_XFER_MODE);
   RdMasterBuffer[0] = Master_I2C_MasterReadByte(Master_I2C_ACK_DATA);               // Read from register
   RdMasterBuffer[1] = Master_I2C_MasterReadByte(Master_I2C_NAK_DATA);               // Read from register, last byte is NAKed
   Master_I2C_MasterSendStop();                                   // End of transaction
   temp++;

When I run the code I see the following on the scope:

MasterReadView.jpg

If I look in the RdMaserBuffer array I do see the first two bytes in the SlaveReceiveBuffer which are 5 and 6.

Now here are my questions. I don't understand the purpose of the line:

   Master_I2C_MasterWriteByte(2);                                 // Indicate which register you want to write to

I put two in the function but that is not correct.

Next, in the SlaveReceiveBuffer I populate it this way:

for(ii = 0; ii < BufSize; ii++)

    {

SlaveSendBuffer[ii] = ii+5;

    }

So the array has 5, 6, 7, 8, 9, 10, 11, 12, 13, 14. Is it possible to only read back a sub-address, like read back 6?

I appears that it always reads back at the started of the array.

Will keep trying.

Thanks,

Joe

0 Likes

Bob,

HI, I'm still playing around. I added the following:

RdMasterBuffer[0] = Master_I2C_MasterReadByte(Master_I2C_ACK_DATA);

RdMasterBuffer[1] = Master_I2C_MasterReadByte(Master_I2C_ACK_DATA);

RdMasterBuffer[2] = Master_I2C_MasterReadByte(Master_I2C_NAK_DATA);

When I run this code I do get back the first 3 bytes in the SlaveReceiveBuffer. Is this good practice, doing ReadBytes back to back?

Joe

0 Likes

Refer to my second reply. Usual, but not required practice is for a slave to offer several "registers" starting at 0 up to the upper limit. This might go up to an unsigned int for external memory.

This behave is programmed into the EZI2C component. First byte (or word) sent by master adresses the register, following reads by master start at the set address and continues up which each read.

Try to replace the slave with an EZI2C component. Now the first byte sent by master as I have shown in the post will address a byte in the buffer.

Bob

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

Hello, thank for helping me learn I2C programming. I've been reading some other posts:

Re: I2C Configuration , Read and Write

I am learning a lot and have some questions.

Here is a simple MasterRead I put together:

uint8 ReadAdd[2] = {1,3};

/***************************************************************************

* MasterRead

****************************************************************************/

uint32 MasterRead(void)

{

    uint8 mydata = 0;

  

    ///// READ STEP 1 - WRITE FIRST ADDRESS OF LOCATION FOR READ THE DATA

    I2CM_MasterWriteBuf(slaveaddress, (uint8 *)ReadAdd, 2, I2CM_MODE_NO_STOP);

    while(1)

    {

        if(0u != (I2CM_MasterStatus() & I2CM_MSTAT_WR_CMPLT))

        {

            break;

        }

    }

    CyDelay(3);

  

    I2CM_MasterReadBuf(slaveaddress, (uint8*)rdmasterbuff, 4,    I2CM_MODE_REPEAT_START);

  

    while(0u == (I2CM_MasterStatus() & (I2CM_MSTAT_ERR_XFER | I2CM_MSTAT_RD_CMPLT)))

            Wait();

  

  return 0;

}

Before I run MasterRead function the SlaveBuffer has the following:

0xC8,

0xC9,

0xCA,

0x0

0x9

0xa

0xb

0xc

0xd

0xe

After I run the MasterRead function the SlaveBuffer has the following:

I2C_MasterReadBuf.bmp

I really don't understand that if you want to simply read from the Slave device, why does the Master write to the SlaveBuffer?  I see that 0x03 got put in to index 1 that is due to the uint8 ReadAdd[2] = {1,3}; line.  Index 1, place a 3.

I look at it this way, the Master writes to the sub-address where he wants to start reading from. Does not make sense to me but that what I see happening. I would think that if a Master was simply reading, then no data in the Slave buffer should be modified.

Is this how it is supposed to work? Maybe my code is wrong.

Could you look it over please?

Thanks,

Joe

0 Likes

The slave buffer result is correct!

with the line

   I2CM_MasterWriteBuf(slaveaddress, (uint8 *)ReadAdd, 2, I2CM_MODE_NO_STOP);

you send two bytes to the slave: 1 and 3. The first byte (1) is interpreted as start address and the second byte (3) is written into the slavebuffer at address 1.
​Bob
0 Likes

Got it, but can you tell me why if the Master is only a doing a read on a Slave buffer why is he modifying the original data as in index[1] was changed from 0xC9 to 0x3? That's the part I don't understand.

0 Likes

The master is not "only a doing a read on a Slave buffer". Your code starts with a I2CM_MasterWriteBuf(). Read and understand my previous post which explains why slavebuff[1] was changed.

Bob

0 Likes

Thanks Bob. I changed the code to

uint8 ReadAdd[2] = {1};

I2CM_MasterWriteBuf(slaveaddress, (uint8 *)ReadAdd, 1, I2CM_MODE_NO_STOP);

With that change I am longer writing/modifying the SlaveBuf when the Master is doing a read.

Thanks again for helping me and thanks for not giving me the boot.

Have a very good day.

Joe

0 Likes