本文主要是介绍Nrf52832 SAADC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一. 测试平台
环境:win10,64位,MDK集成开发环境.
SDK:nRF5_SDK_15.2
协议栈:s132_nrf52_6.1_softdevice.hex.
硬件平台:pca10040开发板
参考例程:nRF5_SDK_15.2.0_9412b96\examples\peripheral\saadc
ADC的最快采样时间为5us采样一个点,如果为两通道扫描采样的话,最快为10us采样一次
二. Application移植
1. 添加相关头文件
#include "nrf_drv_saadc.h"
#include "nrf_drv_ppi.h"
2. SAADC的工作模式
(1). 单次采样模式
SAADC初始化
void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
//
}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_AIN1);err_code = nrf_drv_saadc_init(NULL, saadc_callback);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_channel_init(0, &channel_config);APP_ERROR_CHECK(err_code);}
启动一次ADC采样,获取ADC值
nrf_drv_saadc_sample_convert(0,&saadc_val);
(2).单缓冲中断模式
SAADC初始化,相关中断函数
#define SAMPLES_IN_BUFFER 6
static nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{ float val; if (p_event->type == NRF_DRV_SAADC_EVT_DONE){ret_code_t err_code;//设置好缓存,为下次转换预备缓冲err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);APP_ERROR_CHECK(err_code);int i;for (i = 0; i < p_event->data.done.size; i++){val = p_event->data.done.p_buffer[i] * 3.6 /1024; printf("Voltage = %.3fV\r\n", val);}}
}void saadc_init(void)
{ret_code_t err_code;nrf_saadc_channel_config_t channel_0_config =NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);err_code = nrf_drv_saadc_init(NULL, saadc_callback);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool,SAMPLES_IN_BUFFER);APP_ERROR_CHECK(err_code);
}
启动一次ADC采样,要采样次数等于SAMPLES_IN_BUFFER时,才会进入中断
nrf_drv_saadc_sample();
(3).双缓冲PPI采样
用PPI的方式去触发SAADC,工作方式如下所示:
所以相对之前的初始化会复杂一点,需要初始化定时器,设置采样时间(这个采样时间是采样一个点的时间,如果采样时间设置为400ms,采集5个点,则全部的采样时间为400*5=2s。如果为两个通道,则400ms取两个点,取五次),设置PPI通道,初始化SAADC
#define SAMPLES_IN_BUFFER 5static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t m_ppi_channel;void timer_handler(nrf_timer_event_t event_type, void * p_context)
{}void saadc_sampling_event_init(void)
{ret_code_t err_code;err_code = nrf_drv_ppi_init();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);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();/* setup ppi channel so that timer compare event is triggering sample task in SAADC */err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);APP_ERROR_CHECK(err_code);err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,timer_compare_event_addr,saadc_sample_task_addr);APP_ERROR_CHECK(err_code);
}void saadc_sampling_event_enable(void)
{ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);APP_ERROR_CHECK(err_code);
}void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{if (p_event->type == NRF_DRV_SAADC_EVT_DONE){ret_code_t err_code;err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);APP_ERROR_CHECK(err_code);int i;for (i = 0; i < SAMPLES_IN_BUFFER; i++){NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);}}
}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);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_channel_init(0, &channel_config);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);APP_ERROR_CHECK(err_code);err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);APP_ERROR_CHECK(err_code);}
启动ADC,值需要初始化ADC即可,数据会不停的缓冲在easydma中,每次数据需要及时读取,不然会被覆盖掉。
saadc_init();
saadc_sampling_event_init();
saadc_sampling_event_enable();
防止数据覆盖的方式:
①采样完之后,在ADC中断函数中关掉定时器,等数据处理完再开启定时器,可以用下面两条语句
nrf_drv_timer_disable(&m_timer);
nrf_drv_timer_enable(&m_timer);
② 同时将ADC,PPI,TIMER都关掉,可以有效降低功耗
启动ADC
void ADC_PWM_START(void)
{nrf_saadc_enable();nrf_saadc_task_trigger(NRF_SAADC_TASK_START);nrf_drv_timer_enable(&m_timer);
}
关闭ADC,需要将相关标志位清楚,不然会导致错误
void ADC_PWM_STOP(void)
{nrf_drv_timer_disable(&m_timer);nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);nrf_saadc_event_clear(NRF_SAADC_EVENT_END);nrf_saadc_disable();
}
(4)采样数据的存放方式
在模式2和3中,如果是多通道的话,数据将会交替存放,如下所示:
假设采集数据为3,通道为2
这篇关于Nrf52832 SAADC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!