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.