- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I am trying to establish an I2C connection from PSoC 4 device to PSoC 4.2 using two different development kits, but there doesn't seem to be any transfer of data between the two devices. I initially felt it had to do with the internal pull-up resistors, but the PSoC 4 Kit already have the internal pull up resistors enabled for the GPIO I2C ports (P1.3 and P1.2). I made the interconnections between the two development kits for I2C ports (SDA, SCL) and the GND connection. I am not sure whether it is the differences in Firmware versions that is not letting the devices connect over I2C.
Can anyone review and help me in finding the issue?
Thanks and Regards,
Nandhini Jayapandian
Solved! Go to Solution.
- Labels:
-
PSoC 4 Architecture
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Bob-san,
> There have been some changes done recently which implemented a timeout feature on some devices.
> I would recommend to use the latest actual version.
That is a very good point out!
Although I knew that there is/are APIs which support timeout,
somehow I did not use them yesterday.
So I reviewed my code why I did not use those.
Then I realized that the API with timeout requires "some" more work.
Anyway, I agree that we should use API with timeout support.
I replaced
=======
status = I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDRESS, &tx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
=======
with
=======
status = I2CM_I2CMasterSendStart(I2C_SLAVE_ADDRESS, I2CM_I2C_WRITE_XFER_MODE, TIMEOUT_MSEC) ;
status |= I2CM_I2CMasterWriteByte(tx_data, TIMEOUT_MSEC) ;
status |= I2CM_I2CMasterSendStop(TIMEOUT_MSEC) ;
=======
I replaced
=======
status = I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDRESS, &rx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
=======
with
=======
status = I2CM_I2CMasterSendStart(I2C_SLAVE_ADDRESS, I2CM_I2C_READ_XFER_MODE, TIMEOUT_MSEC) ;
if (status == I2CM_I2C_MSTR_NO_ERROR) {
status = I2CM_I2CMasterReadByte(I2CM_I2C_NAK_DATA, &rx_data, TIMEOUT_MSEC) ;
}
status |= I2CM_I2CMasterSendStop(TIMEOUT_MSEC) ;
=======
I replaced
=======
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
=======
with
=======
timeout_count = 0 ;
while((I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP)&&(timeout_count < TIMEOUT_MSEC)) {
/* wait for the transfer complete */
CyDelay(1) ; /* wait 1ms */
timeout_count++ ;
}
=======
Best Regards,
26-Jul-2019
Motoo Tanaka
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is definitively not the software version. Can you elaborate the correct kits CY8CKIT-0XX. Which Creator version are you using (4.2?)
And can you please post your complete project so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Bob!
As per your comments, I have archived my project files and attached here. Project zip -> Workspace18.cywrk.Archive01.zip is created using PSoC Creator 4.0 and Project zip -> Workspace19.cywrk.Archive.zip is created using PSoC Creator 4.2. In my project, I am using two kits -> CY8CKIT-042 (Slave) and CY8CKIT-040 (Master). I made the I2C (SDA and SCL) and Ground (GND) connections between the two development kits before programing them. Later used PSoC Creator 4.0 to program CY8CKIT-040 and PSoC Creator 4.2 to program CY8CKIT-042. Also, I am a bit confused with the addressing. In the I2C Slave configuration, I could see the default address to be set as 0x08 for CY8CKIT-042. But I couldn't find proper references online for addresses that are already assigned for the devices (like FRAM, PSoC 4 MCU, PSoC 5LP) on the Cypress development kit.
It will be great if you will be able to review my code.
Thanks and Regards,
Nandhini Jayapandian
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The address range for normal I2C is from 0x01 to 0x78. When you get an I2C device (EEPROM, FRam etc) the dataseet will show its default address. This can be changed on some devices using an additional pin, consult datasheet for that feature.
PSoCs as a slave do not have a fixed slave address. Instead this is programmable and can be set to any of the valid addresses.
Very tricky is to use a PSoC4 or 5, create a master AND a slave within the same chip. So you can debug and checkout easily the communication without having to program two different devices. An example is attached.
Is there any reason why you are using two different Creator versions? There have been some changes done recently which implemented a timeout feature on some devices. I would recommend to use the latest actual version.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Bob-san,
> There have been some changes done recently which implemented a timeout feature on some devices.
> I would recommend to use the latest actual version.
That is a very good point out!
Although I knew that there is/are APIs which support timeout,
somehow I did not use them yesterday.
So I reviewed my code why I did not use those.
Then I realized that the API with timeout requires "some" more work.
Anyway, I agree that we should use API with timeout support.
I replaced
=======
status = I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDRESS, &tx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
=======
with
=======
status = I2CM_I2CMasterSendStart(I2C_SLAVE_ADDRESS, I2CM_I2C_WRITE_XFER_MODE, TIMEOUT_MSEC) ;
status |= I2CM_I2CMasterWriteByte(tx_data, TIMEOUT_MSEC) ;
status |= I2CM_I2CMasterSendStop(TIMEOUT_MSEC) ;
=======
I replaced
=======
status = I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDRESS, &rx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
=======
with
=======
status = I2CM_I2CMasterSendStart(I2C_SLAVE_ADDRESS, I2CM_I2C_READ_XFER_MODE, TIMEOUT_MSEC) ;
if (status == I2CM_I2C_MSTR_NO_ERROR) {
status = I2CM_I2CMasterReadByte(I2CM_I2C_NAK_DATA, &rx_data, TIMEOUT_MSEC) ;
}
status |= I2CM_I2CMasterSendStop(TIMEOUT_MSEC) ;
=======
I replaced
=======
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
=======
with
=======
timeout_count = 0 ;
while((I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP)&&(timeout_count < TIMEOUT_MSEC)) {
/* wait for the transfer complete */
CyDelay(1) ; /* wait 1ms */
timeout_count++ ;
}
=======
Best Regards,
26-Jul-2019
Motoo Tanaka
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
As I have never tried to use I2C as Slave, I took the chance.
I let the master send 0x00, 0x01, 0x02 .. one byte each loop
then let the slave receive a byte and return 0xFF - (received value)
so that I can tell that the master is receiving correct data.
At first it seemed to be too complicated to use a couple of boards,
so I used two I2C modules in one CY8CKIT-042.
The schematic was like
I assigned pins as
The board with jumper wires
main.c
======================
#include "project.h"
#include "stdio.h"
#define TIMEOUT_MSEC 100
#define I2C_SLAVE_ADDRESS 0x13
#define WRITE_BIT (0u)
#define READ_BIT (1u)
#define BUF_SIZE 32
uint8_t master_rx_buf[BUF_SIZE] ;
uint8_t master_tx_buf[BUF_SIZE] ;
uint8_t slave_write_buf[BUF_SIZE] ;
uint8_t slave_read_buf[BUF_SIZE] ;
char str[64] ; /* print buffer */
void print(char *str)
{
UART_PutString(str) ;
}
void init_hardware(void)
{
UART_Start() ;
I2CS_I2CSlaveInitReadBuf(slave_read_buf, BUF_SIZE) ;
I2CS_I2CSlaveInitWriteBuf(slave_write_buf, BUF_SIZE) ;
I2CS_Start() ;
I2CM_Start() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "I2C Test (%s %s)\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
uint8_t tx_data = 0 ;
uint8_t rx_data = 0 ;
int status ;
init_hardware() ;
splash() ;
for(;;)
{
I2CS_I2CSlaveInitWriteBuf(slave_write_buf, BUF_SIZE) ;
sprintf(str, "Master Sending [0x%02X] ... ", tx_data) ;
print(str) ;
status = I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDRESS, &tx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
if (status == I2CM_I2C_MSTR_NO_ERROR) {
print("OK\n") ;
} else {
sprintf(str, "Failed with Error [0x%02X]\n", status & 0xFF) ;
print(str) ;
}
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
if (I2CS_I2CSlaveGetWriteBufSize()) {
sprintf(str, "Slave Recived [0x%02X]\n", slave_write_buf[0]) ;
print(str) ;
slave_read_buf[0] = 0xFF - slave_write_buf[0] ;
I2CS_I2CSlaveInitReadBuf(slave_read_buf, BUF_SIZE) ;
I2CM_I2CMasterClearReadBuf() ;
print("Master Reading ... ") ;
status = I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDRESS, &rx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
CyDelay(100) ;
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
if (status == I2CM_I2C_MSTR_NO_ERROR) {
sprintf(str, " [0x%02X} received\n", rx_data) ;
} else {
sprintf(str, "Failed with Error [0x%02X]\n", status & 0xFF) ;
}
print(str) ;
}
print("\n") ;
tx_data = (tx_data + 1) % 0x100 ;
CyDelay(2000) ;
}
}
======================
The Tera Term log looked like
It seemed to be working.
So now I separated the project in to two projects
Master schematic
Master pin assign
main.c (master)
========================
#include "project.h"
#include "stdio.h"
#define TIMEOUT_MSEC 100
#define I2C_SLAVE_ADDRESS 0x13
#define WRITE_BIT (0u)
#define READ_BIT (1u)
#define BUF_SIZE 32
uint8_t master_rx_buf[BUF_SIZE] ;
uint8_t master_tx_buf[BUF_SIZE] ;
char str[64] ; /* print buffer */
void print(char *str)
{
UART_PutString(str) ;
}
void init_hardware(void)
{
UART_Start() ;
I2CM_Start() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "I2C Test (%s %s)\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
uint8_t tx_data = 0 ;
uint8_t rx_data = 0 ;
int status ;
init_hardware() ;
splash() ;
for(;;)
{
sprintf(str, "Master Sending [0x%02X] ... ", tx_data) ;
print(str) ;
status = I2CM_I2CMasterWriteBuf(I2C_SLAVE_ADDRESS, &tx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
if (status == I2CM_I2C_MSTR_NO_ERROR) {
print("OK\n") ;
} else {
sprintf(str, "Failed with Error [0x%02X]\n", status & 0xFF) ;
print(str) ;
}
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
I2CM_I2CMasterClearReadBuf() ;
print("Master Reading ... ") ;
status = I2CM_I2CMasterReadBuf(I2C_SLAVE_ADDRESS, &rx_data, 1, I2CM_I2C_MODE_COMPLETE_XFER) ;
CyDelay(100) ;
while(I2CM_I2CMasterStatus() == I2CM_I2C_MSTAT_XFER_INP) {
; /* wait for the transfer complete */
}
if (status == I2CM_I2C_MSTR_NO_ERROR) {
sprintf(str, " [0x%02X} received\n", rx_data) ;
} else {
sprintf(str, "Failed with Error [0x%02X]\n", status & 0xFF) ;
}
print(str) ;
print("\n") ;
tx_data = (tx_data + 1) % 0x100 ;
CyDelay(2000) ;
}
}
========================
Slave schematic
Slave pin assign
main.c (slave)
========================
#include "project.h"
#include "stdio.h"
#define TIMEOUT_MSEC 100
#define I2C_SLAVE_ADDRESS 0x13
#define WRITE_BIT (0u)
#define READ_BIT (1u)
#define BUF_SIZE 32
uint8_t slave_write_buf[BUF_SIZE] ;
uint8_t slave_read_buf[BUF_SIZE] ;
char str[64] ; /* print buffer */
void print(char *str)
{
UART_PutString(str) ;
}
void init_hardware(void)
{
UART_Start() ;
I2CS_I2CSlaveInitReadBuf(slave_read_buf, BUF_SIZE) ;
I2CS_I2CSlaveInitWriteBuf(slave_write_buf, BUF_SIZE) ;
I2CS_Start() ;
CyGlobalIntEnable; /* Enable global interrupts. */
}
void splash(void)
{
sprintf(str, "I2C Slave Test (%s %s)\n", __DATE__, __TIME__) ;
print(str) ;
}
int main(void)
{
init_hardware() ;
splash() ;
for(;;)
{
slave_write_buf[0] = 0 ;
I2CS_I2CSlaveInitWriteBuf(slave_write_buf, BUF_SIZE) ;
while(I2CS_I2CSlaveGetWriteBufSize() == 0) {
;
}
sprintf(str, "Slave Recived [0x%02X]\n", slave_write_buf[0]) ;
print(str) ;
slave_read_buf[0] = 0xFF - slave_write_buf[0] ;
I2CS_I2CSlaveInitReadBuf(slave_read_buf, BUF_SIZE) ;
sprintf(str, "Slave Set data to [0x%02X]\n", slave_read_buf[0]) ;
print(str) ;
}
}
========================
Then I connected the boards like
SCL <-> SCL
SDA <-> SDA
GND <-> GND
The TeraTerm log (Master)
Tera Term log (Slave)
As I wrote at the beginning, this was my first code using I2C slave,
so there must be better/other ways of writing codes.
But at least it seems to be working.
Also as you can see from the picture, as I don't have 040 board,
I used a couple of CY8CKIT-042, so please re-target Slave project to 040 board.
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Moto,
Thank you very much for the detailed explanation on your project. In my project, I have used two different kits (CY8CKIT-040 -> Master and CY8CKIT-042 -> Slave). The below attached files are created in two different PSoC creator versions (4.0 and 4.2). Also I was not clear whether there are any updates in addressing that was made to the CY8CKIT-042, I proceeded with the code using 0x08 as the slave address for CY8CKIT-042.
I will try to run your code as reference on my system and then try correcting my code based on my requirement. Attached my project files for reference.
Workspace18.cywrk.Archive01.zip (Created using PSoC Creator 4.0) -> Contains the Master code for CY8CKIT-040
Workspace19.cywrk.Archive.zip (Created using PSoC Creator 4.2) -> Contains Slave code for CY8CKIT-042
Thanks and Regards,
Nandhini Jayapandian