- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am new to Cypress, trying to get a UDB I2C master to work. I have successfully fetched the device ID from my test I2c slave device, an ADXL345 accelerometer. However I have two problems:
1) Most of the time, the address that the I2C master puts on the bus right after the start bit is to address 1. With enough resets of the debugger, the I2C master will occasionally get the correct 0x53 address on the bus. When that happens, the slave responds correctly and data makes it into my buffer, and all return values are zero.
2) Even if the address was correct in #1, the final stop bit of the 2nd cycle (the I2C read) will hang on this line in the I2C_MasterSendStop function: while(I2C_WAIT_STOP_COMPLETE(I2C_CSR_REG)). I don't see the STOP bit on the scope either. If I put in a breakpoint before the function and then single step, I see the STOP condition on the scope and it completes.
For #1, what do I need to do to get the I2C Master ready to go to work on the correct address all of the time?
For #2, do I need to check a flag before I call on the I2C_MasterSendStop function?
Complete project attached. Code snippet from main follows:
#include <project.h>
uint8 buffer[10];
uint8 results[20];
void ReadRegs(void)
{
uint8 i=0;
results[i++] = I2C_MasterClearStatus(); // This was added but didn't help
results[i++] = I2C_MasterSendStart( 0x53, 0 ); // start write
results[i++] = I2C_MasterWriteByte( 0x0 ); // Register 0
//results[i++] = I2C_MasterSendStop(); // Commented out, switched to Restart but didn't matter
results[i++] = I2C_MasterSendRestart( 0x53, 1 ); // Turnaround for next cycle
buffer[0] = I2C_MasterReadByte( 1 ); // Read 1 byte
results[i++] = I2C_MasterSendStop(); // stop - This never completes at full speed
while (1)
;
}
int main()
{
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
I2C_Start();
ReadRegs();
}
Solved! Go to Solution.
- Labels:
-
PSoC 3
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The hints address both of your problem, when you leave your slave in an indeterminate state anything may happen.
In the generated file I2C.h you will find (near line 274) the #defines for ACK, NAK and the XFER_MODEs.
So use for reading the I2C_NAK_DATA.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Takes a bit of time to find your error. You do not use the #defines for the second parameter in I2C_MasterSendStart() and I2C_MasterSendRestart() which you can see in the .h file. When you use READ_XFER_MODE and WRITE_XFER_MODE your intentions become more visible (at least for me).
Same for ACK and NAK where you should use I2C_ACK_DATA or I2C_NAK_DATA and here we are: The last byte red must be done with a I2C_NAK_DATA which will distinguish a multiple read last byte from the others.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Bob, I can't seem to follow what you are trying to say... Is this advice for problem #1, #2 or both? The second parameter in I2C_MasterSendStart() can ony be 0 or 1. What do you mean that I do not use the #define? Which .h file? What are READ_XFER_MODE and WRITE_XFER_MODE and do I need to set those? It sounds like I need to set an I2C_NAK_DATA, somehow.
Sorry, just trying to get my bearings. I don't know where to look yet.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The hints address both of your problem, when you leave your slave in an indeterminate state anything may happen.
In the generated file I2C.h you will find (near line 274) the #defines for ACK, NAK and the XFER_MODEs.
So use for reading the I2C_NAK_DATA.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I got this to work for anyone who needs something similar. I created my example from another example that I found here and it didn't have the #defines. Once I added those and the I2C_NAK_DATA as Bob suggested, everything worked. The following is the resulting code:
#include <project.h> uint8 buffer[10]; uint8 results[20]; void ReadRegs(void) { uint8 ss, i=0; results[i++] = I2C_MasterClearStatus(); results[i++] = I2C_MasterSendStart( 0x53, I2C_WRITE_XFER_MODE ); // start results[i++] = I2C_MasterWriteByte( 0x0 ); // Register 0 (start) //results[i++] = I2C_MasterSendStop(); // stop results[i++] = I2C_MasterSendRestart( 0x53, I2C_READ_XFER_MODE ); // read data buffer[0] = I2C_MasterReadByte(I2C_NAK_DATA ); results[i++] = I2C_MasterSendStop(); // stop while (1) ; } int main() { CyGlobalIntEnable; /* Enable global interrupts. */ /* Place your initialization/startup code here (e.g. MyInst_Start()) */ CyDelay(100); I2C_Start(); CyDelay(100); ReadRegs(); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fine that you have got it to work, David!
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi.could u runing adxl345 with spi or i2c?because i cant solved this problem!!!
can u give me your complete project for learning, how i can to do?
tanks...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please check example project available at element14.
Interfacing ADXL345 with I2C component.
Please note the example is using PsoC4, it should be easy to extract the IMU system part and port it to PSoC5LP.
Thanks
JOBIN GT
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thanks dear Jobin.why this link is not open?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried, the link openes without problems.
Bob