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初始化

  1. #include <stdbool.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include "app_uart.h"
  5. #include "app_error.h"
  6. #include "nrf_delay.h"
  7. #include "nrf.h"
  8. #include "bsp.h"
  9. #include "app_uart.h"
  10. #include "nrf_drv_saadc.h"
  11. #define UART_TX_BUF_SIZE 256 //uart 发送软件缓存大小(字节数)
  12. #define UART_RX_BUF_SIZE 256 //uart 接收软件缓存大小(字节数)
  13. //saadc回调函数
  14. void saadc_callback(nrf_drv_saadc_evt_t const *p_event){}
  15. //saadc初始化函数
  16. void saadc_init(void)
  17. {
  18. ret_code_t err_code;
  19. //定义SAADC初始化结构体
  20. //使用默认的宏初始化时需要指定该通道的模拟输入引脚
  21. //具体的引脚分布参考数据手册
  22. nrf_saadc_channel_config_t mmysaadc=
  23. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
  24. //初始化SAADC,注册事件回调函数,注意因为使用了阻塞模式
  25. //所以可以不用回调函数,但是nrf_drv_saadc_init()要求必须提供回调函数
  26. //所以这里要注册回调函数,无论有没有用到
  27. err_code=nrf_drv_saadc_init(NULL,saadc_callback);
  28. APP_ERROR_CHECK(err_code);
  29. //初始化SAADC通道0
  30. err_code = nrf_drv_saadc_channel_init(0, &mmysaadc);
  31. APP_ERROR_CHECK(err_code);
  32. }
  33. //uart事件回调函数
  34. void uart_error_handle(app_uart_evt_t * p_event)
  35. {
  36. if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
  37. {
  38. APP_ERROR_HANDLER(p_event->data.error_communication);
  39. }
  40. else if (p_event->evt_type == APP_UART_FIFO_ERROR)
  41. {
  42. APP_ERROR_HANDLER(p_event->data.error_code);
  43. }
  44. }
  45. //初始化串口
  46. void usart_init()
  47. {
  48. uint32_t err_code;
  49. //定义一个uart配置结构体
  50. const app_uart_comm_params_t comm_params =
  51. {
  52. RX_PIN_NUMBER, //定义uart接收引脚
  53. TX_PIN_NUMBER, //定义uart发送引脚
  54. RTS_PIN_NUMBER, //定义uart RTS引脚,注意流控关闭后虽然定义了RTS和CTS引脚,但是不起作用
  55. CTS_PIN_NUMBER, //定义uart CTS引脚
  56. APP_UART_FLOW_CONTROL_DISABLED, //关闭uart流控
  57. false,
  58. UART_BAUDRATE_BAUDRATE_Baud115200 //uart波特率
  59. };
  60. //初始化app uart,注册uart事件回调函数
  61. APP_UART_FIFO_INIT(&comm_params,
  62. UART_RX_BUF_SIZE,
  63. UART_TX_BUF_SIZE,
  64. uart_error_handle,
  65. APP_IRQ_PRIORITY_LOWEST,
  66. err_code);
  67. APP_ERROR_CHECK(err_code);
  68. }
  69. /**********************************************************************************************
  70. * 描 述 : main函数
  71. * 入 参 : 无
  72. * 返回值 : 无
  73. ***********************************************************************************************/
  74. int main(void)
  75. {
  76. nrf_saadc_value_t saadc_val;
  77. float voltage=9.99;; //转化后的电压值
  78. usart_init(); //初始化串口
  79. saadc_init(); //初始化SAADC
  80. while(true)
  81. {
  82. //启动一次ADC采样
  83. nrf_drv_saadc_sample_convert(0,&saadc_val);
  84. voltage=(float)saadc_val*3.6/1024;
  85. printf("voltage=%f\n",voltage);
  86. nrf_delay_ms(300); //延时300ms
  87. printf("saadc_val=V%d\n", saadc_val);
  88. }
  89. }

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

  1. #define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
  2. { \
  3. .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
  4. .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
  5. .gain = NRF_SAADC_GAIN1_6, \
  6. .reference = NRF_SAADC_REFERENCE_INTERNAL, \
  7. .acq_time = NRF_SAADC_ACQTIME_10US, \
  8. .mode = NRF_SAADC_MODE_SINGLE_ENDED, \
  9. .pin_p = (nrf_saadc_input_t)(PIN_P), \
  10. .pin_n = NRF_SAADC_INPUT_DISABLED \
  11. }

注意1

初始化宏配置SAADC通道的参数如下

ADC输入正极电阻配置:旁路电阻梯

ADC输入负极电阻配置:旁路电阻梯

增益:1/6

参考电压:内部0.6V

采样时间:10US

模式:单端输入

突发模式:禁止

ADC输入正极连接的模拟输入引脚

ADC输入负极连接的模拟输入引脚:不连接

注意2

  1. err_code=nrf_drv_saadc_init(NULL,saadc_callback);

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

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

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

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

  1. #define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(PIN_P, PIN_N) \
  2. { \
  3. .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
  4. .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
  5. .gain = NRF_SAADC_GAIN1_6, \
  6. .reference = NRF_SAADC_REFERENCE_INTERNAL, \
  7. .acq_time = NRF_SAADC_ACQTIME_10US, \
  8. .mode = NRF_SAADC_MODE_DIFFERENTIAL, \
  9. .pin_p = (nrf_saadc_input_t)(PIN_P), \
  10. .pin_n = (nrf_saadc_input_t)(PIN_N) \
  11. }

主函数:

  1. int main(void)
  2. {
  3. nrf_saadc_value_t saadc_val;
  4. float voltage=9.99;; //转化后的电压值
  5. usart_init(); //初始化串口
  6. saadc_init(); //初始化SAADC
  7. while(true)
  8. {
  9. //启动一次ADC采样
  10. nrf_drv_saadc_sample_convert(0,&saadc_val);
  11. //这里saadc_val变成了差分值
  12. voltage=(float)saadc_val*3.6/1024;
  13. printf("voltage=%f\n",voltage);
  14. nrf_delay_ms(300); //延时300ms
  15. printf("saadc_val=V%d\n", saadc_val);
  16. }
  17. }

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

  1. //定义SAADC采样数据缓存
  2. //定义SAADC采样缓存数组大小
  3. //只有采样结果存满该缓存之后,才会产生SAADC采样完成事件
  4. #define SAMPLES_IN_BUFFER 1
  5. //定义SAADC采样缓存数组大小
  6. nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
  7. //定义该变量用来保存SAADC采样的次数
  8. static uint32_t m_adc_evt_counter;
  1. //SAADC初始化函数
  2. void saadc_init(void)
  3. {
  4. ret_code_t err_code;
  5. //定义SAADC初始化结构体
  6. //使用默认的宏初始化时需要指定该通道的模拟输入引脚
  7. //具体的引脚分布参考数据手册
  8. nrf_saadc_channel_config_t mmysaadc=
  9. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
  10. //初始化SAADC,注册事件回调函数,
  11. //注意,本例使用的是非阻塞模式,非阻塞模式下,采样完成后以事件
  12. //的方式通知应用程序,应用程序在事件回调函数中读取采样数据
  13. err_code=nrf_drv_saadc_init(NULL,saadc_callback);
  14. APP_ERROR_CHECK(err_code);
  15. //初始化SAADC通道0
  16. err_code = nrf_drv_saadc_channel_init(NULL, &mmysaadc);
  17. APP_ERROR_CHECK(err_code);
  18. //设置好缓存,等待应用程序启动采样
  19. err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);
  20. APP_ERROR_CHECK(err_code);
  21. }

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

  1. ret_code_t nrf_drv_saadc_buffer_convert (
  2. nrf_saadc_value_t * buffer,
  3. uint16_t size
  4. )
  5. Function for issuing conversion of data to the buffer.
  6. Parameters:
  7. [in] buffer Result buffer.
  8. [in] size Buffer size in words.
  1. //saadc回调函数
  2. void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
  3. {
  4. float val; //保存SAADC采样数据计算的实际电压值
  5. if(p_event->type == NRF_DRV_SAADC_EVT_DONE) //Event generated when the buffer is filled with samples
  6. {
  7. ret_code_t err_code;
  8. //设置好缓存,为下一次采样准备
  9. err_code=nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer,
  10. SAMPLES_IN_BUFFER);
  11. APP_ERROR_CHECK(err_code);
  12. int i;
  13. //串口打印采样次数
  14. printf("ADC event number:%d\r\n",(int)m_adc_evt_counter);
  15. for(i=0;i<SAMPLES_IN_BUFFER;i++)
  16. {
  17. val=p_event->data.done.p_buffer[i]*3.6/1024;
  18. printf("Voltage = %.3fV\r\n", val);
  19. }
  20. //采样次数加1
  21. m_adc_evt_counter++;
  22. }
  23. }

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

5.5电池电压采样

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

  1. //定义SAADC采样缓存数组大小
  2. #define SAMPLES_IN_BUFFER 3
  3. //定义SAADC采样缓存数组
  4. static nrf_saadc_value_t m_buffer_pool[SAMPLES_IN_BUFFER];
  1. /***********************************************************
  2. *函数介绍:初始化SAADC
  3. 通道0 采集电位器电压 P004
  4. 通道1 采集光敏电阻电压 P002
  5. 通道2 采样芯片供电电压 不需要外接引脚
  6. *输入参数:
  7. *输出参数:
  8. *返回值:无
  9. ************************************************************/
  10. void saadc_init(void)
  11. {
  12. ret_code_t err_code;
  13. //定义SAADC采样通道0初始化配置结构体变量,并用默认参数初始化
  14. nrf_saadc_channel_config_t channel_0_config=
  15. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
  16. channel_0_config.gain=NRF_SAADC_GAIN1_6;
  17. channel_0_config.reference=NRF_SAADC_REFERENCE_INTERNAL; //使用内部的0.6V作为参考电压
  18. //定义SAADC采样通道1初始化配置结构体,并用默认参数初始化
  19. nrf_saadc_channel_config_t channel_1_config=
  20. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
  21. channel_1_config.gain=NRF_SAADC_GAIN1_6;
  22. channel_1_config.reference=NRF_SAADC_REFERENCE_INTERNAL; //使用内部的0.6V作为参考电压
  23. //定义SAADC采样通道2初始化配置结构体
  24. nrf_saadc_channel_config_t channel_2_config=
  25. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(SAADC_CH_PSELP_PSELP_VDD);
  26. channel_2_config.gain=NRF_SAADC_GAIN1_6;
  27. channel_2_config.reference=NRF_SAADC_REFERENCE_INTERNAL; //使用内部的0.6V作为参考电压
  28. //初始化SAADC
  29. err_code=nrf_drv_saadc_init(NULL,saadc_callback);
  30. APP_ERROR_CHECK(err_code);
  31. //初始化SAADC的通道0
  32. err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
  33. APP_ERROR_CHECK(err_code);
  34. err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
  35. APP_ERROR_CHECK(err_code);
  36. err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
  37. APP_ERROR_CHECK(err_code);
  38. //使用双缓存
  39. //设置好第一个缓存
  40. err_code=nrf_drv_saadc_buffer_convert(m_buffer_pool,SAMPLES_IN_BUFFER);
  41. APP_ERROR_CHECK(err_code);
  42. // //设置好第二个缓存
  43. // err_code=nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
  44. // APP_ERROR_CHECK(err_code);
  45. }

注意

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

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

nRF52832的SAADC的更多相关文章

  1. nRF52832开发日志--SAADC调试

    今天各种事情比较多.......技术活时间略少,就搞了这一项~ 52832的ADC和之前51822系列还是有蛮大差别的: 1.支持差分输入方式,测量结果为两输入端口电压差的转换的有符号数值,这个功能对 ...

  2. nRF52832定时器

    1概述 定时器能够被配置为两种模式:定时模式和计数模式,nrf52832有五个定时器,timer0--timer4 . 2常用得函数 函数功能:初始化定时器 ret_code_t nrf_drv_ti ...

  3. Nordic Semiconductor nRF52832 蓝牙智能多协议单芯片解决方案荣获《中国电子商情》编辑选择奖

    挪威奥斯陆 – 2016年4月11日 – Nordic Semiconductor ASA (OSE: NOD) 赢得<中国电子商情>颁发的"2015年编辑选择奖",其 ...

  4. nRF52系列——nRF52832来袭

    nRF52系列——nRF52832来袭 Nordic凭借着在无线技术的数十年深耕,推出第一个μBlue芯片-- nRF8001.其低功耗等特性在当时吸引了无数厂商的目光,并将这产品应用到多个领域,再之 ...

  5. 废旧鼠标先别丢,用来学习nRF52832 的QDEC

    刚发现nRF52832有一个 QDEC,SDK13.0中还有驱动,但是不太友好.  如果大家有废旧鼠标,建议拆一个编码器下来“学习”.鼠标的一般原理如下: 图一 图中那个SW4 ALPS EC10E  ...

  6. NRF52832与W25Q80通信

    1 NRF52832SPI主机的功能描述 nRF52832SPIM的主要特征 3个SPI实例 支持SPI的模式0到模式3 支持DMA Individual selection of IO pin fo ...

  7. nrf52832板子焊接后总结的经验

    将之前打的nrf52832的板子拿到手了,经过一番焊接和调试后,发现了一些问题,因为是第一次画板焊接调试,很多地方做的不好,现在将自己的一些经验总结如下: 1 在制板之前,丝印层有必要好好的检查,建议 ...

  8. nRF52832无法加载协议栈文件

    使用keil向nRF52832下载程序时报错 Error:Flash Download failed-Could not load file"..\..\..\..\compoents\so ...

  9. 关于NRF52832能否被替代的详解

    ULP无线系统级芯片 nRF52832是用于ULP无线应用的功能强大的多协议单芯片解决方案.它结合了业界性能最佳的Nordic最新无线收发器.ARM Cortex M4F CPU和512kB闪存及64 ...

随机推荐

  1. shell 中的小技巧

    去掉最后一个字符 sed 's/.$//' awk '{sub(/.$/,"")}1' awk '{printf $0"\b \n"}' [root@ ~]# ...

  2. k8s环境搭建

    mirantis 有个培训, 提供了安装脚本 git clone https://bitbucket.org/mirantis-training/kd100-scripts 网络采用的是calico ...

  3. 辅助模块:udp_sweep

    辅助模块:udp_sweep 模块介绍 使用udp对指定IP地址主机进行udp扫描 实践过程 利用该模块填写目的IP来对目的IP地址进行扫描 从结果可以看到扫描结果显示扫描过程放出了13个探针,发现了 ...

  4. volatile的陷阱

         对于volatile关键字,大部分C语言的教程都是一笔带过,并没有做太深入的分析,所以这里简单的整理了一些 关于volatile的使用注意事项.实际上从语法上来看volatile和const ...

  5. 从输入URL到页面显示发生了什么

    阅读目录 1.输入地址 2.浏览器查找域名的 IP 地址 3.浏览器向 web 服务器发送一个 HTTP 请求 4.服务器的永久重定向响应 5.浏览器跟踪重定向地址 6.服务器处理请求 7.服务器返回 ...

  6. Linux使用——Linux命令——Linux文件压缩和解压使用记录

    一:tar(可压缩可解压) tar命令是Unix/Linux系统中备份文件的可靠方法,几乎可以工作于任何环境中,它的使用权限是所有用户.但是tar本身只是一个文件打包工具,只有和其他工具组合时才具有压 ...

  7. 获取当前的日期时间 格式“yyyy-MM-dd HH:MM:SS”

    function getNowFormatDate() {     var date = new Date();     var seperator1 = "-";     var ...

  8. Android 充电信息的获取【转】

    本文转载自:https://blog.csdn.net/wateryi/article/details/50834821 在android系统中,电池信息是由BatteryService.java统一 ...

  9. php的pear编程: phpDocumentor的使用?

    pfc: php基础类库: pecl: php扩展公共库 pear: php extension and application repository. php的扩展和应用库 phar: ['fa:] ...

  10. Docker 搭建Spark 依赖sequenceiq/spark:1.6镜像

    使用Docker-Hub中Spark排行最高的sequenceiq/spark:1.6.0. 操作: 拉取镜像: [root@localhost home]# docker pull sequence ...