Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)

最近做手表项目用到TWI总线,一个用来驱动oled,一个用来驱动三轴加速度传感器。因为两个模块并的驱动时序不一样,所以分开两个twi总线来驱动它们。这里用到了sdk里面的nrf_drv_twi.c。

一、首先来看看NORDIC的twi总线有哪些特性

Listed here are the main features for TWIM:
• I2C compatible
• 100 kbps, 250 kbps, or 400 kbps
• Support for clock stretching
• EasyDMA

  1. 兼容I2C协议
  2. 时钟频率有100k,250k,400k可以选择
  3. 支持时钟扩展
  4. 支持简易DMA

二、框架图

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第1张图片

三、TWI的时序图

1.写从设备

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第2张图片

2.读从设备
(1)
Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第3张图片

(2)

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第4张图片

四、举例

  1. 这次做计步功能用到了bma423,阅读datasheet的知读写时序如下

1)写时序

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第5张图片

写从设备相对简单 :

#define MAX_WRITE_LENGTH  200
static bool twi_write_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t *write_data, uint16_t len)
{
    ret_code_t err_code;
    
    uint8_t data[MAX_WRITE_LENGTH] ;
    
    if(len> MAX_WRITE_LENGTH -1)
    {
        return false;
    }
    
    data[0] = reg_addr;
    memcpy(&data[1], write_data, len);
    
    m_xfer_done =false;
    err_code = nrf_drv_twi_tx(&m_twi_bma423, slave_addr, data, len+1, false);
    APP_ERROR_CHECK(err_code); 
    
    while (m_xfer_done == false);  
    
    return true;
}

需要注意的是这里的slave_addr是7位的从设备地址,最低位的读写位不需要你管, 观察上图可以知道这里的slvave address是0x18。
另外因为这个函数封装要求把register address和write_data分开,所以这里需要把它们合并成data,再一起发送。

data[0] = reg_addr;
memcpy(&data[1], write_data, len);
err_code = nrf_drv_twi_tx(&m_twi_bma423, slave_addr, data, len+1, false);

2)读时序

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第6张图片

读从设备和我们见到的传统时序不太一样,这里要求发从设备地址–>再发寄存器地址–>不发停止位–> 再发从设备地址-- >再发数据。
所以读函数如下

static bool_t twi_read_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len)
{
    
    ret_code_t err_code;

    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi_bma423, slave_addr, ®_addr,      1, true);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);  
    


    m_xfer_done =false;
    err_code = nrf_drv_twi_rx(&m_twi_bma423, slave_addr , read_data, len);
    APP_ERROR_CHECK(err_code);    
    while (m_xfer_done == false);  

    return true;
    
}

这里我们看到第一次调用nrf_drv_twi_tx 发送函数,最后一个函数参数是true就是 no_stop为true,没有停止位, 然后再调用nrf_drv_twi_rx接收函数。

其他函数如下:

#define BMA423_SALVE_ADDRESS 0x18
/* TWI instance ID. */
#define TWI_BMA423_INSTANCE_ID     1 //使用twi1

/* TWI instance. */
static const nrf_drv_twi_t m_twi_bma423 = NRF_DRV_TWI_INSTANCE(TWI_BMA423_INSTANCE_ID);

/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;

/**
 * @brief UART initialization.
 */
static void bsp_bma423_twi_init(void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_bma423_config = {
       .scl                = PIN_BMA423_SCLK,
       .sda                = PIN_BMA423_SDA,
       .frequency          = NRF_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = true,
    };

    err_code = nrf_drv_twi_init(&m_twi_bma423, &twi_bma423_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi_bma423);
}


/**
 * @brief TWI events handler.
 */
static void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
               //NRF_LOG_INFO("twi rx done");// data_handler(m_sample);
            }
            else if(p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
            {
               // NRF_LOG_INFO("twi tx done");
            }
            m_xfer_done = true;
            break;
            
        case NRF_DRV_TWI_EVT_ADDRESS_NACK:
             NRF_LOG_INFO("Error event: NACK received after sending the address.");
            break;
        
        case NRF_DRV_TWI_EVT_DATA_NACK:
             NRF_LOG_INFO("Error event: NACK received after sending a data byte.");
             break;


        default:
            break;
    }
}

另外 sdk_config.h中要开启TWI功能

//  TWI1_ENABLED - Enable TWI1 instance
//==========================================================
#ifndef TWI1_ENABLED
#define TWI1_ENABLED 1
#endif

欢迎关注个人公众号“低功耗蓝牙技术研究及推广”

Nordic系列芯片讲解五( Nordic sdk中nrf_drv_twi的使用)_第7张图片

你可能感兴趣的:(Nordic芯片详解)