nRF52832的SAADC
SAADC部分思维导图
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)
{
}
}
nRF52832的SAADC的更多相关文章
- nRF52832开发日志--SAADC调试
今天各种事情比较多.......技术活时间略少,就搞了这一项~ 52832的ADC和之前51822系列还是有蛮大差别的: 1.支持差分输入方式,测量结果为两输入端口电压差的转换的有符号数值,这个功能对 ...
- nRF52832定时器
1概述 定时器能够被配置为两种模式:定时模式和计数模式,nrf52832有五个定时器,timer0--timer4 . 2常用得函数 函数功能:初始化定时器 ret_code_t nrf_drv_ti ...
- Nordic Semiconductor nRF52832 蓝牙智能多协议单芯片解决方案荣获《中国电子商情》编辑选择奖
挪威奥斯陆 – 2016年4月11日 – Nordic Semiconductor ASA (OSE: NOD) 赢得<中国电子商情>颁发的"2015年编辑选择奖",其 ...
- nRF52系列——nRF52832来袭
nRF52系列——nRF52832来袭 Nordic凭借着在无线技术的数十年深耕,推出第一个μBlue芯片-- nRF8001.其低功耗等特性在当时吸引了无数厂商的目光,并将这产品应用到多个领域,再之 ...
- 废旧鼠标先别丢,用来学习nRF52832 的QDEC
刚发现nRF52832有一个 QDEC,SDK13.0中还有驱动,但是不太友好. 如果大家有废旧鼠标,建议拆一个编码器下来“学习”.鼠标的一般原理如下: 图一 图中那个SW4 ALPS EC10E ...
- NRF52832与W25Q80通信
1 NRF52832SPI主机的功能描述 nRF52832SPIM的主要特征 3个SPI实例 支持SPI的模式0到模式3 支持DMA Individual selection of IO pin fo ...
- nrf52832板子焊接后总结的经验
将之前打的nrf52832的板子拿到手了,经过一番焊接和调试后,发现了一些问题,因为是第一次画板焊接调试,很多地方做的不好,现在将自己的一些经验总结如下: 1 在制板之前,丝印层有必要好好的检查,建议 ...
- nRF52832无法加载协议栈文件
使用keil向nRF52832下载程序时报错 Error:Flash Download failed-Could not load file"..\..\..\..\compoents\so ...
- 关于NRF52832能否被替代的详解
ULP无线系统级芯片 nRF52832是用于ULP无线应用的功能强大的多协议单芯片解决方案.它结合了业界性能最佳的Nordic最新无线收发器.ARM Cortex M4F CPU和512kB闪存及64 ...
随机推荐
- Python之字符编码(一)
一.了解字符编码的知识储备? 1.计算机基础知识? 计算机中所有的软件文件(包括:操作系统)都存储在硬盘,启动计算机,计算机需要把系统文件都去到内存中. 2.文本编辑器存取文件的原理(nodepad+ ...
- 01: docker 基本使用
1.1 docker基础 1.docker与虚拟机比较 2.docker版本 1. 社区版(Community Edition, CE) 2. 企业版(Enterprise Edition, EE) ...
- Python3基础 iter+next 进行迭代时超出了范围 产生StopIteration异常
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- codevs1017乘积最大
codevs1017 乘积最大 题目描述 Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场 ...
- FastQC结果详解
REF https://www.plob.org/article/5987.html 解压后,查看html格式的结果报告.结果分为如下几项: 结果分为绿色的"PASS",黄色的&q ...
- java 之 音乐播放代码
//需求:通过代码播放音乐 //1.读取文件 //2.将音乐文件放到播放代码中 //3.播放 public static void main(String[] args) throws Malform ...
- 谷歌大规模机器学习:模型训练、特征工程和算法选择 (32PPT下载)
本文转自:http://mp.weixin.qq.com/s/Xe3g2OSkE3BpIC2wdt5J-A 谷歌大规模机器学习:模型训练.特征工程和算法选择 (32PPT下载) 2017-01-26 ...
- MPU6050
MPU6050: Pitch,Roll,Yaw旋转方向遵循右手定则 pith角 –绕Y轴(俯仰) 范围:±90° ,与旋转方向相反转是增大 -- 抬头为正,低头为负 roll角 –绕X轴( ...
- Linux 下终端 C 语言控制光标的技巧
// 清除屏幕 #define CLEAR() printf("\033[2J") // 上移光标 #define MOVEUP(x) printf("\033[%dA& ...
- 17秋 SDN课程 第二次上机作业
1.控制器floodlight所示可视化图形拓扑的截图,及主机拓扑连通性检测截图 拓扑 连通性 2.利用字符界面下发流表,使得'h1'和'h2' ping 不通 流表截图 连通性 3.利用字符界面下发 ...