nRF52832的SAADC

SAADC部分思维导图
1327401-20180727233102944-1627575370.jpg

1ADC原理

1.1主要特点

1)8/10/12分辨率,使用过采样可达到14位分辨率
2)多达8个通道
单端输入时使用1个通道,2个通道可组成差分输入
单端和差分输入时均可配置为扫描模式
3)满量程输入范围(0 to VDD)
参考芯片数据手册

1.2功能概述

参考芯片数据手册

1.3工作模式

1)单次模式
2)连续模式
使用ADC内部定时器实现定时采样
使用nRF52832的通用定时器定时同PPI触发采样,实现连续采样
3)扫描模式
当使能一个ADC通道,ADC工作于单次模式,当使能的通道数量大于1个,ADC进入扫描模式

2SAADC的应用步骤

2.1SAADC库文件

2.2SAADC驱动的应用

1)阻塞模式
2)非阻塞模式
3)门限监测

3相关寄存器

4重要的库函数

5DEMO

5.1阻塞模式-单端输入采样

SAADC初始化

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#include "app_uart.h"

#include "nrf_drv_saadc.h"

#define UART_TX_BUF_SIZE 256      //uart 发送软件缓存大小(字节数)
#define UART_RX_BUF_SIZE 256      //uart 接收软件缓存大小(字节数) 

//saadc回调函数
void saadc_callback(nrf_drv_saadc_evt_t const *p_event){}
//saadc初始化函数
void saadc_init(void)
{
    ret_code_t err_code;
    //定义SAADC初始化结构体
    //使用默认的宏初始化时需要指定该通道的模拟输入引脚
    //具体的引脚分布参考数据手册
    nrf_saadc_channel_config_t mmysaadc=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    //初始化SAADC,注册事件回调函数,注意因为使用了阻塞模式
    //所以可以不用回调函数,但是nrf_drv_saadc_init()要求必须提供回调函数
    //所以这里要注册回调函数,无论有没有用到
    err_code=nrf_drv_saadc_init(NULL,saadc_callback);
    APP_ERROR_CHECK(err_code);
    //初始化SAADC通道0
    err_code = nrf_drv_saadc_channel_init(0, &mmysaadc);
    APP_ERROR_CHECK(err_code);
    
}
//uart事件回调函数
void uart_error_handle(app_uart_evt_t * p_event)
{
    if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_communication);
    }
    else if (p_event->evt_type == APP_UART_FIFO_ERROR)
    {
        APP_ERROR_HANDLER(p_event->data.error_code);
    }
}
//初始化串口
void usart_init()
{
    uint32_t err_code;
    
      //定义一个uart配置结构体
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,  //定义uart接收引脚
        TX_PIN_NUMBER,  //定义uart发送引脚
        RTS_PIN_NUMBER, //定义uart RTS引脚,注意流控关闭后虽然定义了RTS和CTS引脚,但是不起作用
        CTS_PIN_NUMBER, //定义uart CTS引脚 
        APP_UART_FLOW_CONTROL_DISABLED,   //关闭uart流控
        false,
        UART_BAUDRATE_BAUDRATE_Baud115200 //uart波特率
    };
    //初始化app uart,注册uart事件回调函数
    APP_UART_FIFO_INIT(&comm_params,
                         UART_RX_BUF_SIZE,
                         UART_TX_BUF_SIZE,
                         uart_error_handle,
                         APP_IRQ_PRIORITY_LOWEST,
                         err_code);

    APP_ERROR_CHECK(err_code);  
    
}
/**********************************************************************************************
 * 描  述 : main函数
 * 入  参 : 无
 * 返回值 : 无
 ***********************************************************************************************/ 
int main(void)
{
    nrf_saadc_value_t saadc_val;
    float voltage=9.99;;  //转化后的电压值
    usart_init();  //初始化串口
    saadc_init();  //初始化SAADC
    while(true) 
    {
        //启动一次ADC采样
        nrf_drv_saadc_sample_convert(0,&saadc_val);
        voltage=(float)saadc_val*3.6/1024;
                printf("voltage=%f\n",voltage);
        nrf_delay_ms(300);  //延时300ms
        printf("saadc_val=V%d\n", saadc_val);

    }
}

SAADC初始化包括两部分:SAADC驱动程序初始化,SAADC通道配置。nrf_drv_saadc.h中定义了两个带输入参数的初始化宏

#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
{                                                      \
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,         \
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED,         \
    .gain       = NRF_SAADC_GAIN1_6,                   \
    .reference  = NRF_SAADC_REFERENCE_INTERNAL,        \
    .acq_time   = NRF_SAADC_ACQTIME_10US,              \
    .mode       = NRF_SAADC_MODE_SINGLE_ENDED,         \
    .pin_p      = (nrf_saadc_input_t)(PIN_P),          \
    .pin_n      = NRF_SAADC_INPUT_DISABLED             \
}

注意1
初始化宏配置SAADC通道的参数如下
ADC输入正极电阻配置:旁路电阻梯
ADC输入负极电阻配置:旁路电阻梯
增益:1/6
参考电压:内部0.6V
采样时间:10US
模式:单端输入
突发模式:禁止
ADC输入正极连接的模拟输入引脚
ADC输入负极连接的模拟输入引脚:不连接

注意2

err_code=nrf_drv_saadc_init(NULL,saadc_callback);

SAADC初始化函数nrf_drv_saadc_init(),如果没有提供SAADC配置结构体即第一个参数为NULL,这时驱动会使用“sdk_config.h”文件默认参数配置SAADC

5.2阻塞模式-差分输入采样

SAADC初始化
//saadc初始化函数
void saadc_init(void)
{
    ret_code_t err_code;
    //定义SAADC初始化结构体
    //使用默认的宏初始化时需要指定该通道的模拟输入引脚
    //具体的引脚分布参考数据手册
    nrf_saadc_channel_config_t mmysaadc=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN2,NRF_SAADC_INPUT_AIN0);
    //初始化SAADC,注册事件回调函数,注意因为使用了阻塞模式
    //所以可以不用回调函数,但是nrf_drv_saadc_init()要求必须提供回调函数
    //所以这里要注册回调函数,无论有没有用到
    err_code=nrf_drv_saadc_init(NULL,saadc_callback);
    APP_ERROR_CHECK(err_code);
    //初始化SAADC通道0
    err_code = nrf_drv_saadc_channel_init(0, &mmysaadc);
    APP_ERROR_CHECK(err_code);
    
}

NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL宏有两个输入参数,对应通道的正极模拟输入引脚和负极模拟输入引脚

#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \
{                                                                       \
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,                          \
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED,                          \
    .gain       = NRF_SAADC_GAIN1_6,                                    \
    .reference  = NRF_SAADC_REFERENCE_INTERNAL,                         \
    .acq_time   = NRF_SAADC_ACQTIME_10US,                               \
    .mode       = NRF_SAADC_MODE_DIFFERENTIAL,                          \
    .pin_p      = (nrf_saadc_input_t)(PIN_P),                           \
    .pin_n      = (nrf_saadc_input_t)(PIN_N)                            \
}

主函数:

int main(void)
{
    nrf_saadc_value_t saadc_val;
    float voltage=9.99;;  //转化后的电压值
    usart_init();  //初始化串口
    saadc_init();  //初始化SAADC
    while(true) 
    {
        //启动一次ADC采样
        nrf_drv_saadc_sample_convert(0,&saadc_val);
        //这里saadc_val变成了差分值
        voltage=(float)saadc_val*3.6/1024;
                printf("voltage=%f\n",voltage);
        nrf_delay_ms(300);  //延时300ms
        printf("saadc_val=V%d\n", saadc_val);

    }
}

5.3非阻塞模式-单缓存采样

//定义SAADC采样数据缓存
//定义SAADC采样缓存数组大小
//只有采样结果存满该缓存之后,才会产生SAADC采样完成事件
#define SAMPLES_IN_BUFFER 1

//定义SAADC采样缓存数组大小
nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
//定义该变量用来保存SAADC采样的次数
static uint32_t m_adc_evt_counter;
//SAADC初始化函数
void saadc_init(void)
{
    ret_code_t err_code;
    //定义SAADC初始化结构体
    //使用默认的宏初始化时需要指定该通道的模拟输入引脚
    //具体的引脚分布参考数据手册
    nrf_saadc_channel_config_t mmysaadc=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    //初始化SAADC,注册事件回调函数,
    //注意,本例使用的是非阻塞模式,非阻塞模式下,采样完成后以事件
    //的方式通知应用程序,应用程序在事件回调函数中读取采样数据
    err_code=nrf_drv_saadc_init(NULL,saadc_callback);
    APP_ERROR_CHECK(err_code);
    //初始化SAADC通道0
    err_code = nrf_drv_saadc_channel_init(NULL, &mmysaadc);
    APP_ERROR_CHECK(err_code);
    
    //设置好缓存,等待应用程序启动采样
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    
}

nrf_drv_saadc_buffer_convert函数将SAADC工作于非阻塞模式,可将SAADC配置为就绪状态,但是不会触发采样

ret_code_t nrf_drv_saadc_buffer_convert (   
    nrf_saadc_value_t *     buffer,
    uint16_t    size 
)

Function for issuing conversion of data to the buffer.

Parameters:
[in]    buffer  Result buffer.
[in]    size    Buffer size in words.
//saadc回调函数
void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
{
    float val;  //保存SAADC采样数据计算的实际电压值
    
    if(p_event->type == NRF_DRV_SAADC_EVT_DONE)  //Event generated when the buffer is filled with samples
    {
        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;
        //串口打印采样次数
        printf("ADC event number:%d\r\n",(int)m_adc_evt_counter);
        
        for(i=0;i<SAMPLES_IN_BUFFER;i++)
        {
            val=p_event->data.done.p_buffer[i]*3.6/1024;    
      printf("Voltage = %.3fV\r\n", val);           
        }
        
        //采样次数加1
        m_adc_evt_counter++;
        
    }
    
}

5.4非阻塞模式-双缓存采样

5.5电池电压采样

5.6三个通道同时采样-定时器触发

//定义SAADC采样缓存数组大小
#define SAMPLES_IN_BUFFER 3

//定义SAADC采样缓存数组
static nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
/***********************************************************
*函数介绍:初始化SAADC
            通道0 采集电位器电压   P004
            通道1 采集光敏电阻电压 P002
            通道2 采样芯片供电电压 不需要外接引脚
*输入参数:
*输出参数:
*返回值:无
************************************************************/
void saadc_init(void)
{
    ret_code_t err_code;
    //定义SAADC采样通道0初始化配置结构体变量,并用默认参数初始化
    nrf_saadc_channel_config_t channel_0_config=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    channel_0_config.gain=NRF_SAADC_GAIN1_6;
    channel_0_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用内部的0.6V作为参考电压
    
    
    //定义SAADC采样通道1初始化配置结构体,并用默认参数初始化
        nrf_saadc_channel_config_t channel_1_config=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    channel_1_config.gain=NRF_SAADC_GAIN1_6;
    channel_1_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用内部的0.6V作为参考电压

    //定义SAADC采样通道2初始化配置结构体
    nrf_saadc_channel_config_t channel_2_config=
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(SAADC_CH_PSELP_PSELP_VDD);

    channel_2_config.gain=NRF_SAADC_GAIN1_6;
    channel_2_config.reference=NRF_SAADC_REFERENCE_INTERNAL;  //使用内部的0.6V作为参考电压

    //初始化SAADC
    err_code=nrf_drv_saadc_init(NULL,saadc_callback);
  APP_ERROR_CHECK(err_code);
    
    //初始化SAADC的通道0
    err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
  APP_ERROR_CHECK(err_code);
    
    //使用双缓存
    //设置好第一个缓存
    err_code=nrf_drv_saadc_buffer_convert(m_buffer_pool,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);
}

注意
三个通道采样,分别配置为通道0,1,2

//saadc回调函数
void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
{
      ret_code_t err_code;
    float val;  //保存SAADC采样数据计算的实际电压值
      if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            //设置好缓存,为下一次采样做准备
              err_code=nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer,
                                                    SAMPLES_IN_BUFFER);
               APP_ERROR_CHECK(err_code);
               //读取采样结果,使用串口发送
               for(uint32_t i=0;i<SAMPLES_IN_BUFFER;i++)
               {
                val=p_event->data.done.p_buffer[i]*3.6/1024;    
//                printf("Voltage = %.3fV\r\n", val);
                     switch(i)
                     {
                        case 0:printf("AIN2=%f\r\n",val); break;
                        case 1:printf("AIN0=%f\r\n",val); break;
                        case 2:printf("VDD=%f\r\n",val); break;
                        default:break;
                     }
               }
        }
}
/**********************************************************************************************
 * 描  述 : main函数
 * 入  参 : 无
 * 返回值 : 无
 ***********************************************************************************************/ 
int main(void)
{
    nrf_saadc_value_t saadc_val;
    usart_init();  //初始化串口
  saadc_init();  //初始化SAADC
  timers_init(); //定时器初始化函数
    while(true) 
    {

    }
}

转载于:https://www.cnblogs.com/Manual-Linux/p/9380267.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值