Hi everyone,
I am having problems in getting the twi peripheral to work properly with the accelerometer I am using ( NXP MM8653FC).
I am getting some wierd issues, firstly I can't store the result from the TWI_RX in a local variable
for example
static void MM8653_deviceID() { m_xfer_done = false; ret_code_t err_code; uint8_t reg[1] = {WHO_AM_I}; uint8_t rx_buff; err_code = nrf_drv_twi_tx(&m_twi, MM8653FC, reg, 1, true); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } err_code = nrf_drv_twi_rx(&m_twi, MM8653FC, &rx_buff, 1); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } NRF_LOG_INFO("ID: %X \r\n", rx_buff[0]); NRF_LOG_FLUSH(); }
Does not work, as the value of rx_buff doesnt get updated unless I move into outside of the function as a global variable or delcare it as static.
I understand this is to do with the local variable being out of scope but I can't see how as the function does not exit until the TWI operation has finished through
checking the !m_xfer_done flag.
My other problem is this, if I put
memset(rx_buf, 0, sizeof(rx_buf));just before twi_rx is called, then rx_buff ( uint8_t array) is always 0 and doesnt get updated, which I am finding trouble to understand why.
Finally I can't call two seperate twi_rx functions back to back, I get a fatal error. If I put a delay of 500ms, I get garbage data, ie instead of getting 5A for the id I get 4??
int main(void) { APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_INFO("\r\nTWI sensor example\r\n"); NRF_LOG_FLUSH(); twi_init(); nrf_delay_ms(500); MM8653_init(); MM8653_deviceID(); while (true) { nrf_delay_ms(1000); MM8653_readData(); nrf_delay_ms(1000); MM8653_deviceID(); NRF_LOG_FLUSH(); } }
ReadData function
static void MM8653_readData() { m_xfer_done = false; ret_code_t err_code; uint8_t reg[1] ={OUT_X_MSB}; err_code = nrf_drv_twi_tx(&m_twi,MM8653FC, reg, 1, true); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } err_code = nrf_drv_twi_rx(&m_twi, MM8653FC, rx_buff, 1); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } NRF_LOG_INFO("X: %d , Y: %d , Z: %d \r\n", rx_buff[0],rx_buff[1],rx_buff[2]); NRF_LOG_FLUSH(); }
Whole Program Code
#include <stdio.h> #include "boards.h" #include "app_util_platform.h" #include "app_error.h" #include "nrf_drv_twi.h" #include "nrf_delay.h" #define NRF_LOG_MODULE_NAME "APP" #include "nrf_log.h" #include "nrf_log_ctrl.h" /* TWI instance ID. */ #define TWI_INSTANCE_ID 0 /* Acclerometer registers */ #define MM8653FC 0x1D #define CTRL_REG1 0x2A #define OUT_X_MSB 0x01 #define OUT_Y_MSB 0x03 #define OUT_Z_MSB 0x05 #define WHO_AM_I 0x0D /* Indicates if operation on TWI has ended. */ static volatile bool m_xfer_done = false; /* TWI instance. */ static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID); /* Buffer for samples read from temperature sensor. */ static uint8_t m_sample; static uint8_t rx_buff[24]= {0}; /** * @brief TWI events handler. */ void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context) { switch (p_event->type) { case NRF_DRV_TWI_EVT_DONE: m_xfer_done = true; break; default: break; } } /** * @brief UART initialization. */ void twi_init (void) { ret_code_t err_code; const nrf_drv_twi_config_t twi_config = { .scl = TWI_SCL_PIN, .sda = TWI_SDA_PIN, .frequency = NRF_TWI_FREQ_100K, .interrupt_priority = APP_IRQ_PRIORITY_HIGH, .clear_bus_init = false }; err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL); APP_ERROR_CHECK(err_code); nrf_drv_twi_enable(&m_twi); } static void MM8653_deviceID() { m_xfer_done = false; ret_code_t err_code; uint8_t reg[1] = {WHO_AM_I}; err_code = nrf_drv_twi_tx(&m_twi, MM8653FC, reg, 1, true); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } err_code = nrf_drv_twi_rx(&m_twi, MM8653FC, rx_buff, 1); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } NRF_LOG_INFO("ID: %X \r\n", rx_buff[0]); NRF_LOG_FLUSH(); } static void MM8653_init() { m_xfer_done = false; ret_code_t err_code; uint8_t reg[2] = {CTRL_REG1, 0xFF}; err_code = nrf_drv_twi_tx(&m_twi, MM8653FC, reg, sizeof(reg), false); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } } static void MM8653_readData() { m_xfer_done = false; ret_code_t err_code; uint8_t reg[1] ={OUT_X_MSB}; err_code = nrf_drv_twi_tx(&m_twi,MM8653FC, reg, 1, true); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } err_code = nrf_drv_twi_rx(&m_twi, MM8653FC, rx_buff, 1); APP_ERROR_CHECK(err_code); while(!m_xfer_done) { __WFE(); } NRF_LOG_INFO("X: %d , Y: %d , Z: %d \r\n", rx_buff[0],rx_buff[1],rx_buff[2]); NRF_LOG_FLUSH(); } /** * @brief Function for main application entry. */ int main(void) { APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_INFO("\r\nTWI sensor example\r\n"); NRF_LOG_FLUSH(); twi_init(); nrf_delay_ms(500); MM8653_init(); MM8653_deviceID(); while (true) { nrf_delay_ms(1000); MM8653_readData(); nrf_delay_ms(1000); MM8653_deviceID(); NRF_LOG_FLUSH(); } }
Thank you so muhc for the help, much appreicated!
Rgs,
Bryan Hsieh
------------------------------------------------------------------------------------
UPDATE: 21/05/18
Problem solved, it turns out that I forgot to set m_xfer_done to false before the second the transaction causing unpredictable behavior.