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

二、框架图

这里写图片描述

三、TWI的时序图

1.写从设备

这里写图片描述

2.读从设备
(1)
这里写图片描述

(2)

这里写图片描述

四、举例

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

1)写时序

这里写图片描述

写从设备相对简单 :

#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)读时序

这里写图片描述

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

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, &reg_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功能

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

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

在这里插入图片描述

NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE是Nordic Semiconductor公司提供的一个默认的单端输入通道配置宏。该宏用于配置nRF52系列芯片上的SAADC(Successive Approximation Analog-to-Digital Converter)模块的单端输入通道。 在nRF52系列芯片,SAADC模块用于将模拟信号转换为数字信号。SAADC模块可以配置多个输入通道,每个通道可以连接到不同的模拟输入引脚。NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE宏用于配置单端输入通道,其SE表示Single Ended(单端)。 NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE宏的具体配置参数包括: - .resistor_p:选择输入通道的正极电阻,可选值为SAADC_RESISTOR_DISABLED(禁用电阻)、SAADC_RESISTOR_PULLDOWN(下拉电阻)和SAADC_RESISTOR_PULLUP(上拉电阻)。 - .resistor_n:选择输入通道的负极电阻,可选值与resistor_p相同。 - .gain:选择输入通道的增益,可选值为SAADC_GAIN1/4、SAADC_GAIN1/2、SAADC_GAIN1、SAADC_GAIN2、SAADC_GAIN4、SAADC_GAIN8和SAADC_GAIN16。 - .reference:选择参考电压,可选值为SAADC_REFERENCE_INTERNAL(内部参考电压)和SAADC_REFERENCE_VDD4(VDD/4作为参考电压)。 - .acq_time:选择采样时间,可选值为SAADC_ACQTIME_3US、SAADC_ACQTIME_5US、SAADC_ACQTIME_10US、SAADC_ACQTIME_15US、SAADC_ACQTIME_20US、SAADC_ACQTIME_40US和SAADC_ACQTIME_80US。 使用NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE宏可以方便地配置SAADC模块的单端输入通道,以满足不同应用场景的需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值