8 Replies Latest reply on Mar 18, 2016 8:52 AM by user_1377889

    I2C and MMA8451

    jim.schimpf_1583906

      Hi,

         

           I am attempting to use a FreeScale MMA8451 so I read with great interest the post "reading adxl345 data on i2c" and found very similar issues. To read a register on the 8451 just like the adxl345 you have to write the register # to I2C, do a restart then read. My code to do this was just as you suggested for the adx part.

         

          status =  SCB_I2CMasterSendStart(MMA8451Address,SCB_I2C_WRITE_XFER_MODE);
          status |= SCB_I2CMasterWriteByte(reg & 0xff);
          status |= SCB_I2CMasterSendRestart(MMA8451Address,SCB_I2C_READ_XFER_MODE);
          rtnval =  SCB_I2CMasterReadByte(SCB_I2C_ACK_DATA);
          status |= SCB_I2CMasterSendStop();
          if( status != SCB_I2C_MSTR_NO_ERROR )
          {
              rtnval = -1 * status;
          }

         

      This works, but monitoring the I2C bus I see an extra read value 0f 0x00 see the enclosed file (TEK00117.png).  If I remove the SCB_I2CMasterReadByte() in the above the extra byte is not there.  Where is this extra byte coming from ?

         

      Also the application has BLE, FreeRTOS and will be sleeping.  In the main thread I do this:

         

         while( 1 )
          {
              // Setup Accelerometer
              rtnval = initMMA8451(MMA8451_DEFAULT_ADDRESS);  // This is where the register is read
          
              vTaskDelay(5000 *portTICK_RATE_MS  );
       
              i = i + 1;
              SCB_Sleep();
              CyBle_ProcessEvents();
              CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP);
              SCB_Wakeup();
          }

         

      The i = i+1 is to give a breakpoint line.  After two time through the loop it gets stuck in the CY_ISR(CyBLE_Bless_Interrupt) handler and won't proceed.  Removing the DEEPSLEEP line makes no difference. Any suggestions on how to handle this ?

         

      Thank you for the help

         

      --jim schimpf

        • 1. Re: I2C and MMA8451
          user_1377889

          When reading a byte from I2C the last (or only) byte must be NAKed. Might be the cause for the extra byte seen on the bus.

             

           

             

          Bob

          • 2. Re: I2C and MMA8451
            jim.schimpf_1583906

            Thank you I will try this. Found this in the MMA8451 manual.

               

            When performing a multi-byte read or “burst read”, the MMA8451Q automatically increments the received register address commands after a read command is received. Therefore, after following the steps of a single byte read, multiple bytes of data can be read from sequential registers after each MMA8451Q acknowledgment (AK) is received until a no acknowledge (NAK) occurs from the Master followed by a stop condition (SP) signaling an end of transmission. 

               

            As you can see in TEK00118.png it worked.  Thank you very much.

               

            --jim schimpf

            • 3. Re: I2C and MMA8451
              user_1377889

              You are always welcome.

                 

               

                 

              Bob

              • 4. Re: I2C and MMA8451
                jim.schimpf_1583906

                Hi

                   

                After fixing the NAK problem in ReadRegister I then changed the WriteRegister part of the MMA8451 code to this

                   

                    txbuf[0] = 0xff & reg;
                    txbuf[1] = 0xff & value;
                    
                    status = SCB_I2CMasterWriteBuf(MMA8451Address,txbuf,cnt,SCB_I2C_WRITE_XFER_MODE);
                    
                    // Wait for done
                    
                    cnt = SCB_I2CMasterStatus();
                    while( cnt != SCB_I2C_MSTAT_WR_CMPLT )
                    {
                        vTaskDelay(1 *portTICK_RATE_MS  );
                        cnt = SCB_I2CMasterStatus();
                    }

                   

                And now the rest of the MMA8451 initialization works.  Is there a better way to determine when the WriteBuf is done ? Without the wait the next readReg in the MMA8451 codes steps on a partially completed transfer and dies in the I2C code. The spin loop prevents this but is there a better way ?

                   

                The image TEK00119.png shows this top of the screen shows all the register sets.  After I submit this code to Adafruit I will post the library for MMA8451 use here.

                • 5. Re: I2C and MMA8451
                  user_1377889

                  Do not use SCB_I2C_WRITE_XFER_MODE with buffered write, there is a SCB_I2C_MODE_COMPLETE_XFER. Have a look at the transfer modes in datasheet.

                     

                   

                     

                  Bob

                  1 of 1 people found this helpful
                  • 6. Re: I2C and MMA8451
                    jim.schimpf_1583906

                    Thank you, simplified things.  Found writing to the MMA8451 registers too fast caused it to choke.  put a vTaskDelay after write and it works fine. When code working will put a copy here.

                    • 7. Re: I2C and MMA8451
                      jim.schimpf_1583906

                      As promised here is the MMA8451 library for Cypress.  This is a copy of the Adafruit library with the low level I2C routines replaced with Cypress compatible routines.  It doesn't have all the methods the original had as I didn't need them but if you do just copy from the original library.  These methods use the same low level routines so they will just compile in.

                         

                      See Cypress.zip

                         

                      --jim schimpf

                      • 8. Re: I2C and MMA8451
                        user_1377889

                        Thank you for sharing that project with us.

                           

                         

                           

                        Bob