I2C Master sends wrong device address sometimes

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

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();
}

   
0 Likes
1 Solution
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

View solution in original post

0 Likes
9 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Anonymous
Not applicable

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.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Anonymous
Not applicable

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(); }
   
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Fine that you have got it to work, David!

   

 

   

Bob

0 Likes
moro_1580446
Level 5
Level 5
100 replies posted 50 replies posted 25 replies posted

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...

0 Likes
JobinT_31
Employee
Employee
50 solutions authored 25 solutions authored 10 solutions authored

Please check example project available at element14.

   

Interfacing ADXL345 with I2C component.

   

https://www.element14.com/community/community/design-challenges/smarter-life/blog/2013/12/08/psoc-4-...

   

​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

0 Likes
moro_1580446
Level 5
Level 5
100 replies posted 50 replies posted 25 replies posted

thanks dear Jobin.why this link is not open?

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I tried, the link openes without problems.

   

 

   

Bob

0 Likes