- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Solved! Go to Solution.
- Labels:
-
PSoC 5 Device Programming
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using the PSOC5 CY8CKIT-059 kit.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Joe,
Could you double-check if EZI2CDesign code example in PSoC Creator can help you or not?
Thanks,
Ryan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
Thanks
Joe
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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); | ||
} |
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The slave buffer result is correct!
with the line
I2CM_MasterWriteBuf(slaveaddress, (uint8 *)ReadAdd, 2, I2CM_MODE_NO_STOP);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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