- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Solved! Go to Solution.
- Labels:
-
BLE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are always welcome.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for sharing that project with us.
Bob