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

    I2C and MMA8451



           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;


      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

          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.





          • 2. Re: I2C and MMA8451

            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

              You are always welcome.





              • 4. Re: I2C and MMA8451



                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

                  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.





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

                    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

                      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

                        Thank you for sharing that project with us.