ADC Oneshot Read 示例

[English]

示例说明

本示例展示如何初始化、配置、校准 ADC 以及如何使用 ADC 单次采样模式采集模拟输入信号并进行处理。有关 ADC 连续转换模式的说明可参考 模数转换器 (ADC) 单次转换模式驱动

运行方法

示例完整代码见 ADC Oneshot Read 示例。运行前的配置说明、构建与烧录流程详见 adc 目录下的 README.md 文件。

如需自定义配置项及查看默认值,可参考 全局变量/宏定义说明 部分。

头文件说明

本示例所使用的头文件涵盖了 FreeRTOS 任务管理、常用系统工具以及 ADC 驱动等基础模块。为任务创建、ADC 初始化、采集及校准提供支持。

各头文件按功能分类如下:

  1. FreeRTOS 任务调度 :提供任务管理功能,用于创建和管理任务。

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
  1. 系统工具 :提供输入输出、字符串处理、内存管理、日志记录以及定长整数类型支持。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
  1. ADC 驱动及校准 :提供 ADC 单次采样模式初始化、通道配置、原始采样读取、软件校准及电压转换功能。

#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "soc/soc_caps.h"

全局变量/宏定义说明

本示例中涉及的宏定义主要用于定义 GPIO 输入输出引脚以及中断标志位。

宏定义按功能分类如下:

  1. ADC1 通道选择

  • 根据芯片型号选择不同的 ADC1 通道,ESP32 芯片使用通道 4 和 5,其他型号芯片使用通道 2 和 3。

#if CONFIG_IDF_TARGET_ESP32
#define EXAMPLE_ADC1_CHAN0          ADC_CHANNEL_4
#define EXAMPLE_ADC1_CHAN1          ADC_CHANNEL_5
#else
#define EXAMPLE_ADC1_CHAN0          ADC_CHANNEL_2
#define EXAMPLE_ADC1_CHAN1          ADC_CHANNEL_3
#endif
  1. ADC2 通道选择

  • 判断芯片是否支持第二个 ADC 外设(ADC2)。若支持 ADC2,则使能 EXAMPLE_USE_ADC2

#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3
#define EXAMPLE_USE_ADC2            1
#endif

备注

ESP32-C3 芯片由于硬件限制不支持 ADC2。

  • 判断 EXAMPLE_USE_ADC2 是否被使能,若已使能,则指定 ADC2 使用通道 0。

#if EXAMPLE_USE_ADC2
#if CONFIG_IDF_TARGET_ESP32
#define EXAMPLE_ADC2_CHAN0          ADC_CHANNEL_0
#else
#define EXAMPLE_ADC2_CHAN0          ADC_CHANNEL_0
#endif
#endif
  1. ADC 衰减设置:衰减配置决定了 ADC 的输入电压可测范围及其线性精度。不同衰减档位对应不同的有效测量电压区间,具体档位可参考 ADC 驱动,各衰减档位和 ADC 有效输入电压测量范围的对应关系可参考 技术规格书 > ADC 特性

  • 设置 ADC 通道的衰减为 12 dB,用于扩展可测电压范围。

#define EXAMPLE_ADC_ATTEN           ADC_ATTEN_DB_12
  1. 定义全局变量,用于保存数据:

  • 定义变量 adc_raw[][] 用于存储 ADC 原始采样结果,二维数组的第一维表示通道编号,本示例中最多支持 2 个通道;第二维表示每个通道连续采样的数据点数量,本示例中为 10 个。

  • 定义变量 voltage[][] 用于存储将原始采样值转换为电压后的结果,数组结构与 adc_raw 对应,即同一个索引位置的 adc_rawvoltage 元素表示同一次采样在原始数值和电压数值下的对应关系。

任务函数说明

在使用 ADC 采集模拟输入信号前,需要对外设进行校准,以修正采样误差。校准能够提高测量精度,将原始数据转换为实际电压值,适应不同硬件条件,并提升整体应用的可靠性。

本示例提供了两个相关任务函数:一个用于执行软件校准并生成校准句柄,另一个用于注销已创建的校准方案并释放相关资源。

执行软件校准

example_adc_calibration_init() 为 ADC 校准初始化函数,用于指定 ADC 单元与通道的校准配置,并创建相应的校准句柄。

参数解释

传入参数

参数功能

参数说明

unit

指定要校准的 ADC 单元

例如 ADC_UNIT_1ADC_UNIT_2,确定要校准的 ADC 外设。

channel

指定要校准的 ADC 通道号

对应 ADC 外设中的具体通道,用于采集模拟输入信号。

atten

设置通道的衰减值

调整可测输入电压范围。

out_handle

ADC 校准句柄

输出参数,返回创建成功的校准方案句柄,用于后续将原始采样值转换为电压。

该函数的执行逻辑为:

  1. 创建变量:

  • 创建 ADC 校准句柄 handle 并初始化为 NULL

  • 创建返回值变量 ret 并初始化为 ESP_FAIL,用于错误检查和日志输出,确保调用者能根据不同返回值采取不同处理。

  • 创建标志位 calibrated 并初始化为 false,在该示例中用于标记当前是否已经成功完成校准,避免重复校准。

  1. 曲线拟合方案:当宏 ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED 有效且尚未校准时执行。

  • 打印当前方案日志。

  • 通过结构体 adc_cali_curve_fitting_config_t 配置校准参数。结构体成员包括使用的 ADC 单元、通道、衰减系数以及原始数据输出分辨率。

  • 调用 adc_cali_create_scheme_curve_fitting() 根据配置的结构体创建曲线拟合校准方案,并将返回值保存至变量 ret

  • 当返回值为 ESP_OK 时,修改标志位为 true,标明当前已完成校准,并保存生成的校准句柄至 handle

  1. 线性拟合方案:当宏 ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED 有效且尚未校准时执行。

  • 打印当前方案日志。

  • 通过结构体 adc_cali_line_fitting_config_t 配置校准参数。结构体成员包括使用的 ADC 单元、衰减系数以及原始数据输出分辨率。

  • 调用 adc_cali_create_scheme_line_fitting() 根据配置的结构体创建曲线拟合校准方案,并将返回值保存至变量 ret

  • 当返回值为 ESP_OK 时,修改标志位为 true,标明当前已完成校准,并保存生成的校准句柄至 handle

  1. 输出结果并返回状态

  • 将函数内生成的校准句柄保存到传参 out_handle

  • 根据拟合方案返回值(校准成功、跳过校准或校准失败)打印对应的日志。

  • 返回标志位 calibrated,用于指示校准是否成功。

注销已创建的校准方案

example_adc_calibration_deinit() 用于注销已创建的 ADC 校准方案,释放相关资源,确保系统在不再使用该校准句柄时不会产生内存泄漏或占用。

参数解释

传入参数

参数功能

参数说明

handle

已创建的 ADC 校准句柄

用于指定需要注销的校准方案并释放相关资源。

该函数的执行逻辑为:

  1. 注销曲线拟合方案:当宏 ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED 有效时执行。

  • 打印当前注销的校准方案日志。

  • 调用 adc_cali_delete_scheme_curve_fitting() 注销指定校准方案,并通过返回值检查操作是否成功,确保资源释放正确。

  1. 注销线性拟合方案:当宏 ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED 有效时执行。

  • 打印当前注销的校准方案日志。

  • 调用 adc_cali_delete_scheme_line_fitting() 注销指定校准方案,并通过返回值检查操作是否成功,确保资源释放正确。

主函数说明

本函数展示如何初始化 ADC 单元、配置通道、执行软件校准,并循环采集 ADC 原始数据和校准后的电压值。

  1. 初始化 ADC1 外设

  2. 配置 ADC1 的通道

  3. 校准初始化 ADC1:

  • 为每个需要校准的通道创建 ADC 校准句柄 adc_cali_handle_t 用于保存创建成功的校准方案实例。可初始化为 NULL

  • 对每个通道分别调用校准初始化函数 example_adc_calibration_init(),获取对应的校准句柄,用于后续将原始 ADC 值转换为电压值。

  1. 初始化 ADC2 外设:当宏 EXAMPLE_USE_ADC2 有效时执行。

  2. 配置 ADC2 的通道:当宏 EXAMPLE_USE_ADC2 有效时执行。

  3. 校准初始化 ADC2:当宏 EXAMPLE_USE_ADC2 有效时执行。

  • 为每个需要校准的通道创建 ADC 校准句柄 adc_cali_handle_t 用于保存创建成功的校准方案实例。可初始化为 NULL

  • 对每个通道分别调用校准初始化函数 example_adc_calibration_init(),获取对应的校准句柄,用于后续将原始 ADC 值转换为电压值。

  1. 循环采集与打印:该步骤在数据处理循环中执行。

  • 调用 adc_oneshot_read() 获取 ADC1 通道 0 的原始采样数据并保存至 adc_raw[0][0]。进一步介绍及参数说明可参考 ADC 驱动

  • 打印原始采样数据。

  • 通过校准标志位判断当前校准状态,若校准成功,调用 adc_cali_raw_to_voltage() 转换原始采样数据为电压值,保存至 voltage[0][0] 并打印。进一步介绍及参数说明可参考 ADC 驱动

  • 延时 1 秒后重复上述流程获取 ADC1 通道 1 的原始采样数据及电压值并保存至对应数组。

  • 若 ADC2 通道启用,延时 1 秒后重复上述流程获取 ADC2 的原始采样数据及电压值并保存至对应数组。

  1. 资源释放:

  • 循环结束或退出时调用 adc_oneshot_del_unit() 删除指定 ADC 单元。创建了多个 ADC 单元时,必须分别调用该函数逐一删除。进一步介绍及参数说明可参考 ADC 驱动

  • 调用 example_adc_calibration_deinit() 注销已创建的校准方案,因此每个通道均需对应调用一次注销函数。

备注

在实际应用中,ADC 数据采集任务通常为长期运行或常驻任务,因此该步骤一般不被执行,但可以用于防止潜在的程序异常或内存泄漏。