6 Replies Latest reply on Nov 4, 2017 6:17 AM by user_1377889

    How to reading out a Register with I2C?

    heimo.gaicher_1629436

      Hi!

      I want to read out the ID number of an I2C chip (TCS3472) with my PSoC 4S Pioneer Kit. So i'm still not really familiar with I2C bus and PSoC Controller. Hope, somebode can help or can share an example with me?

       

      What i do is:

       

      1. Write the value 0x1B to Register ENABLE

      2. read out the ID number of the chip

       

      But what i got is not the ID number (see image)

       

      For my test, i used this code:

       

       

       

      #include "project.h"

       

       

      #define I2C_SLAVE_ADDR      (0x29)  // TCS3472 Address

      #define RegisterDeviceID    (0x12)  // Registeraddress of ID

      #define RegisterENABLE      (0x00)  // Registeraddress of Enable Register

      #define PON_AEN_WEN_AIEN    (0x1B); // Value of Enable Register

       

       

      #define BUFFER_SIZE   (2)

       

       

      #define TRANSFER_CMPLT      (0x00)

      #define TRANSFER_ERROR      (0xFF)

       

       

      /* Start and end of packet markers */

      #define PACKET_SOP      (0x01)

      #define PACKET_EOP      (0x17)

       

       

      /* Packet positions */

      #define PACKET_SOP_POS  (0)

      #define PACKET_CMD_POS  (1)

      #define PACKET_STS_POS  (PACKET_CMD_POS)

      #define PACKET_EOP_POS  (2)

       

       

      /* Command valid status */

      #define STS_CMD_DONE    (0x00)

      #define STS_CMD_FAIL    (0xFF)

       

       

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

      *               Macros

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

       

       

      /* Set LED RED color */

      #define RGB_LED_ON_RED  \

                      do{     \

                          LED_RED_Write  (0); \

                          LED_GREEN_Write(1); \

                      }while(0)

       

       

      /* Set LED GREEN color */

      #define RGB_LED_ON_GREEN \

                      do{      \

                          LED_RED_Write  (1); \

                          LED_GREEN_Write(0); \

                      }while(0)

       

       

      /* Set LED TURN OFF */

      #define RGB_LED_OFF \

                      do{ \

                          LED_RED_Write  (1); \

                          LED_GREEN_Write(1); \

                      }while(0)

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

        

       

       

      uint32 WriteCommandPacket()

      {

          uint8  buffer[2];

          uint32 status = 0xFF;     // TRANSFER_ERROR = 0xFF

       

       

          /* Initialize buffer with packet */

          buffer[0] = RegisterENABLE;

          buffer[1] = PON_AEN_WEN_AIEN; 

         

          (void) I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDR, buffer, BUFFER_SIZE, I2CM_I2C_MODE_COMPLETE_XFER);

       

       

          /* Waits until master completes write transfer */

          while (0u == (I2CM_I2CMasterStatus() & I2CM_I2C_MSTAT_WR_CMPLT))

          {

          }

         

              /* Displays transfer status */

          if (0u == (I2CM_I2C_MSTAT_ERR_XFER & I2CM_I2CMasterStatus()))

          {

              /* Check if all bytes was written */

              if (I2CM_I2CMasterGetWriteBufSize() == BUFFER_SIZE)

              {

                  RGB_LED_ON_GREEN;

                  status = TRANSFER_CMPLT;

              }

          }

          else

          {

              RGB_LED_ON_RED;

          }

       

       

          (void) I2CM_I2CMasterClearStatus();

       

       

          return (status);

      }

       

       

      uint32 ReadStatusPacket(void)

      {

          uint8  buffer[2];

         

          buffer[0]= 0x12;        // RegisterDeviceID;

          buffer[1]= 0x00;        // dummy byte

         

          uint32 status = 0xFF;   // TRANSFER_ERROR = 0xFF

       

       

          (void) I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDR, buffer, BUFFER_SIZE, I2CM_I2C_MODE_COMPLETE_XFER);

       

       

          /* Waits until master complete read transfer */

          while (0u == (I2CM_I2CMasterStatus() & I2CM_I2C_MSTAT_RD_CMPLT))

          {

          }

       

       

          /* Displays transfer status */

          if (0u == (I2CM_I2C_MSTAT_ERR_XFER & I2CM_I2CMasterStatus()))

          {

              /* Check packet structure */

              if (I2CM_I2CMasterGetReadBufSize() == BUFFER_SIZE)

              {

                  /* Check packet status */

                  if (STS_CMD_DONE == buffer[PACKET_STS_POS])

                  {

                      RGB_LED_ON_GREEN;

                      status = TRANSFER_CMPLT;

                  }

              }

          }

          else

          {

              RGB_LED_ON_RED;

              status = TRANSFER_ERROR;

          }

       

       

          (void) I2CM_I2CMasterClearStatus();

       

       

          return (status);

      }

       

       

      int main(void)

      {

          I2CM_Start();

         

          CyGlobalIntEnable; /* Enable global interrupts. */

       

       

          for(;;)

          {

              /* Send packet to the slave */

              if (WriteCommandPacket() == 0)

              {

                  /* Read response packet from the slave */

                  if (ReadStatusPacket() == 0)

                      RGB_LED_ON_GREEN;

                  else

                      RGB_LED_ON_RED;

              }

              CyDelay(5); /* Delay between commands */

          }

      }

        • 1. Re: How to reading out a Register with I2C?
          ntan

          If you want to read a register byte from a specified address (0x12) you must access the device as follows.

           

          1) Write the register address 0x12 to the device as a command.

          2) Read one byte from the device.

           

          In the step 1) no data byte is required.

           

          The reason why you receive 0x1B as the read data is because the device's internal address pointer still points the ENABLE register.  If you override the address pointer with the command, you will get the ID field.

           

          Regards,

          Noriaki

          1 of 1 people found this helpful
          • 2. Re: How to reading out a Register with I2C?
            heimo.gaicher_1629436

            Hello Noriaki,

             

            thanks for your hints. I tried to read out but it didn't work.

             

            Please can you post a little code example for reading out a register?

             

            Many thanks

            • 3. Re: How to reading out a Register with I2C?
              ntan

              Please let me know what did you do.

              I cannot provide a working example because I do not have a target device.

               

              Regards,

              Noriaki

              • 4. Re: How to reading out a Register with I2C?
                heimo.gaicher_1629436

                Hello Noriaki,

                 

                first, i write the value 0x1B into the Register Enable on Adress 0x00:

                 

                          #define I2C_SLAVE_ADDR      (0x29)  // TCS3472 Address

                 

                          uint8  writeBuffer[2];

                 

                          writeBuffer[0] = 0x00; // Adress of Register Enable

                          writeBuffer[1] = 0x1B; // Value to set the Register

                      

                          (void) I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDR, writeBuffer, sizeof(writeBuffer), I2CM_I2C_MODE_COMPLETE_XFER);

                 

                On my Analyzer i got:           Start | 0x29WR | ACK | 0x00 | ACK | 0x1B | ACK | STOP

                 

                So this should be ok!

                 

                Then i want to read out the ID-Number of the chip from Address 0x12

                Here you wrote, that i must first send the command 0x12.

                 

                i tried this:

                 

                        uint8  deviceID;

                        uint8  readBuffer[1];

                 

                        readBuffer[0] = 0x12;  // Address of ID number

                       

                        (void) I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDR, readBuffer, sizeof(readBuffer), I2CM_I2C_MODE_COMPLETE_XFER);

                       

                        /* Waits until master completes read transfer */

                        while (0u == (I2CM_I2CMasterStatus() & I2CM_I2C_MSTAT_RD_CMPLT))

                        {

                        }

                       

                        (void) I2CM_I2CMasterClearStatus();   //Clear I2C master status

                 

                        deviceID = readBuffer[0];

                 

                In my understanding, if i use this function, the Master initiate a read condition which write the command 0x12 + RD.

                But what i got on my Analyzer is:       START | 0x29RD | ACK | 0x1B | NAK | STOP |

                 

                I also tried to write the command 0x12 before i used the Read function, but it doesnt work.

                So im confused now!

                • 5. Re: How to reading out a Register with I2C?
                  ntan

                  Thank you for your reply.

                   

                  The WRITE operation requires two I2C accesses.

                   

                  1) Write the register address 0x12 to the device as a command.

                      i2cmTxBuffer[0] = tcs3472RegId;
                      status = I2CM_I2CMasterWriteBuf(tcs3472Address, i2cmTxBuffer, 1, I2CM_I2C_MODE_COMPLETE_XFER);
                      // Wait for transfer completion
                      while (!(I2CM_I2CMasterStatus() & I2CM_I2C_MSTAT_WR_CMPLT)) ;
                  

                   

                  2) Read one byte from the device.

                      status = I2CM_I2CMasterReadBuf(tcs3472Address, i2cmRxBuffer, 1, I2CM_I2C_MODE_COMPLETE_XFER);
                      // Wait for transfer completion
                      while (!(I2CM_I2CMasterStatus() & I2CM_I2C_MSTAT_RD_CMPLT)) ;
                  

                   

                  Please add an I2C-WRITE to specify the register address.

                   

                  I have created an example project using CY8CKIT-044 "PSoC 4 M-Series Pioneer Kit" as attached.

                  GS003349.png

                  The interface protocol of the TCS3472 is similar to the EZI2C component.  So, I put an I2CM component as a host and an EZI2C component as a target on one PSoC 4M device.  Connect SDA and SCL pins of each components and put two pull-up resistors.

                   

                  Regards,

                  Noriaki

                  • 6. Re: How to reading out a Register with I2C?
                    user_1377889

                    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