1 2 Previous Next 16 Replies Latest reply on Oct 25, 2018 10:26 AM by user_80002741

    Help with I2C Slave Write?

    user_80002741

      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

        • 1. Re: Help with I2C Slave Write?
          user_80002741

          I'm using the PSOC5 CY8CKIT-059 kit.

          • 2. Re: Help with I2C Slave Write?
            rzzh

            Hi Joe,

             

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

             

            Thanks,

            Ryan

            • 3. Re: Help with I2C Slave Write?
              bob.marlowe

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

               

              Bob

              • 4. Re: Help with I2C Slave Write?
                user_80002741

                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

                • 5. Re: Help with I2C Slave Write?
                  bob.marlowe

                  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

                  • 6. Re: Help with I2C Slave Write?
                    user_80002741

                    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

                    • 7. Re: Help with I2C Slave Write?
                      user_80002741

                      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);
                      }
                      • 8. Re: Help with I2C Slave Write?
                        bob.marlowe

                        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

                        • 9. Re: Help with I2C Slave Write?
                          user_80002741

                          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

                          • 10. Re: Help with I2C Slave Write?
                            user_80002741

                            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

                            • 11. Re: Help with I2C Slave Write?
                              bob.marlowe

                              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

                              • 12. Re: Help with I2C Slave Write?
                                user_80002741

                                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

                                • 13. Re: Help with I2C Slave Write?
                                  bob.marlowe

                                  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
                                  • 14. Re: Help with I2C Slave Write?
                                    user_80002741

                                    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.

                                    1 2 Previous Next