- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 */
}
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please let me know what did you do.
I cannot provide a working example because I do not have a target device.
Regards,
Noriaki
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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
- 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