NRF52832 ADC的采样触发和采样速度的分析

如何使用ADC 能找到一些例程。但是ADC是怎么控制采样速度的。

有两种AD的采样模式:阻塞(blocking mode)和非阻塞(no-blocking mode)

阻塞模式:
调用函数:nrf_drv_saadc_sample_convert完成采样。采样完成后return采样值。

非阻塞模式:
此模式触发方式有两种CPU显式触发或使用PPI。
1.CPU显式调用函数nrf_drv_saadc_sample实现触发。触发后会调用ADC初始化时写入的回调函数。
2.使用PPI,调用函数nrf_drv_saadc_sample_task_get();实现触发。触发后会调用ADC的初始化时写入的回调函数。

非阻塞模式在触发前都需要调用函数nrf_drv_saadc_buffer_convert(buffer, 1);。这个函数是告诉AD库,采样到的数据保存在buffer变量。采样的次数为1.(次数可以设置多次)

官方此处对两种模式做了介绍,可以查看下
官方AD模式–阻塞与非阻塞介绍

===================================== 分割线 ====================================

如下我对使用PPI模式下的代码做详细解析:

PPI是NORDIC的一个外设。有点像DMA。其会自动将外设数据在没有CPU参与的情况下。将数据存入内存的指定地址。

代码参考是的SDK 外设的SAADC的例程。
nRF5_SDK_15.2.0_9412b96\examples\peripheral\saadc

例程将AD的初始化放到如下三个自定义函数里面在这里插入图片描述
1.通道和缓冲区初始化

//AD初始化
void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);   //定义引脚通道初始化参数结构体。

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);  //初始化ad的回调函数,完成采样周期后,调用saadc_callback
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);//AD引脚通道的初始化。使用默认参数初始化AIN0。
    APP_ERROR_CHECK(err_code);

    //设置AD的缓冲区。调用两次nrf_drv_saadc_buffer_convert是为了实现双缓冲。其传入的内存首地址是不一样的。
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);   //m_buffer_pool是一个二维数组

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

}

2.采样事件的设置

//采样事件的设置
void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();  //初始化PPI
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);  //初始化一个定时器
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 400ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);    //定时器启动。定时器周期为400MS

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();  //开始启动sample

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);//设置PPI
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);    //ppi通道将AD的事件和定时器事件联合
    APP_ERROR_CHECK(err_code);
}

3.使能PPI

涉及到采样速度的地方

1.ADC初始化的时候,需要设置模数转换采集时间。就是芯片引脚到外设产生采集需要10us的时间。
在这里插入图片描述
2.触发时间。如上例中400ms产生一次触发。那么根据上例的配置。缓冲区是5.那么完整的采集周期就是5*400ms=2000ms=2s。那么每2s就会调用一次saadc_callback函数。

3.AD的最大的速度。受制硬件的AD转换速率。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值