How to reading out a Register with I2C?

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

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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 */

    }

}

0 Likes
1 Solution
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

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

View solution in original post

6 Replies
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

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

Anonymous
Not applicable

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

0 Likes
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

Please let me know what did you do.

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

Regards,

Noriaki

0 Likes
Anonymous
Not applicable

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!

0 Likes
lock attach
Attachments are accessible only for community members.
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

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

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