news 2026/9/15 20:25:33

ESP-IDF 模数转换器(ADC)驱动完全指南:oneshot、continuous 与校准原理详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP-IDF 模数转换器(ADC)驱动完全指南:oneshot、continuous 与校准原理详解

ESP-IDF 模数转换器(ADC)驱动完全指南:oneshot、continuous 与校准原理详解

【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf

导读

本文以 ESP-IDF 官方 ADC 编程指南(docs/en/api-reference/peripherals/adc/index.rst)为主线,系统讲解 Espressif SoC 上 ADC(模数转换器)的核心概念——转换原理、原始数据分辨率、参考电压与衰减,并深入剖析其两大驱动模式:oneshot 模式(单次按需采样)与continuous 模式(DMA 高速连续采样),以及用于提升精度的ADC 校准驱动。阅读完本文,你将掌握 ADC 通道的配置方法、原始读数与电压的换算公式、两种模式各自的资源管理与读取流程,并能通过 Kconfig 选项与 IRAM-safe、电源管理等机制在实际项目中正确选型与调优。

一、ADC 核心概念:从模拟电压到数字量

ADC(Analog to Digital Converter)负责将输入模拟电压转换为数字值。ESP-IDF 的 ADC 驱动 API 返回的均是原始数据(raw data),它以数字形式表征模拟输入信号。

1.1 分辨率与原始数据位宽

默认情况下,ADC 原始结果的位宽为12 位,这意味着输入电压范围被划分为 2¹² =4096 个离散电平,由此决定了可检测的最小输入信号变化量。

原始 ADC 结果data对应的电压Vdata计算公式为:

Vdata = data / (2^bitwidth − 1) × Vref

其中:

  • data:ADC 原始结果;
  • bitwidth:ADC 结果分辨率(如 12 位);
  • Vref:ADC 参考电压。

1.2 参考电压 Vref 的制造偏差

按设计,Vref1100 mV。但由于芯片制造工艺差异,不同芯片的实际参考电压可能落在1000 mV ~ 1200 mV之间。这一偏差正是需要 ADC 校准驱动的原因——要获得经过校准的精确电压值,请使用 adc_calibration.rst 中介绍的校准驱动,依据芯片实际的Vref对原始结果进行修正。

从源码角度,adc_cali_handle_t校准句柄与adc_cali_raw_to_voltage()等接口定义在 components/esp_adc/include/esp_adc/adc_cali.h,校准方案接口表adc_cali_scheme_t位于 components/esp_adc/interface/adc_cali_interface.h,其实现分布在 components/esp_adc/adc_cali.c、components/esp_adc/adc_cali_curve_fitting.c 等文件中。

1.3 衰减(Attenuation):扩大测量范围

ADC 只能直接测量0 V ~ Vref范围内的模拟电压。要测量更高电压,可在信号进入 ADC 之前先进行衰减。支持的衰减档位如下表:

衰减档位比例系数 k(约)
0 dBk ≈ 100%
2.5 dBk ≈ 75%
6 dBk ≈ 50%
12 dBk ≈ 25%

衰减档位越高,ADC 能测量的输入电压上限越高。施加衰减后的电压计算公式为:

Vdata = (Vref / k) × (data / (2^bitwidth − 1))

其中k是对应衰减档位的比例值,其余变量含义同前。每个衰减档位对应的具体输入电压范围,请查阅目标芯片数据手册(datasheet)中的 "Electrical Characteristics > ADC Characteristics"(ESP32 则为 "Function Description > Analog Peripherals > Analog-to-Digital Converter (ADC)")章节。

二、ADC 驱动模式总览

ESP-IDF 的 ADC 驱动按使用场景分为两种工作模式:

  • oneshot 模式:适用于单次、按需采样,一次只对一个通道采样,实现简单、资源占用低;
  • continuous 模式:适用于需要周期性或高频连续采集的场景,ADC 自动对一组通道依次采样或对单个通道连续采样,并通过 DMA 将结果高效搬运到内存。

其中 continuous 模式需要芯片支持 DMA(即SOC_ADC_DMA_SUPPORTED)。同一 ADC 单元在同一时刻只能工作于一种模式下,驱动内部已提供互斥保护(详见各模式的硬件限制章节)。

两种模式对应的官方实现分别是 components/esp_adc/adc_oneshot.c 与 components/esp_adc/adc_continuous.c,头文件分别为 components/esp_adc/include/esp_adc/adc_oneshot.h 与 components/esp_adc/include/esp_adc/adc_continuous.h。

三、ADC Oneshot 模式驱动详解

oneshot 模式适合采样频率低、按需触发的应用,例如读取电位器电压、电池电量检测等低频测量任务。

3.1 资源分配:创建与回收 ADC 单元

在 oneshot 驱动视角下,一个 ADC 实例由句柄adc_oneshot_unit_handle_t表示。安装 ADC 实例前需设置初始化配置结构体adc_oneshot_unit_init_cfg_t(定义于 adc_oneshot.h):

  • unit_id:选择 ADC 单元(ADC_UNIT_1 / ADC_UNIT_2),对应芯片上具体的模拟 IO,可查数据手册或使用adc_oneshot_io_to_channel()反查;
  • clk_src:ADC 时钟源,置 0 时驱动回退到默认时钟源(见adc_oneshot_clk_src_t);
  • ulp_mode:是否在 ULP 模式下使用 ADC。

配置完成后调用adc_oneshot_new_unit()创建单元,成功则返回 ADC 单元句柄。该函数可能因参数非法、内存不足等失败;特别地,当目标 ADC 实例已被占用时会返回ESP_ERR_NOT_FOUND,可用SOC_ADC_PERIPH_NUM宏获知芯片可用 ADC 数量。不再使用时调用adc_oneshot_del_unit()回收实例及其软硬件资源。

adc_oneshot_unit_handle_t adc1_handle; adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, .ulp_mode = ADC_ULP_MODE_DISABLE, }; ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); // ... 使用完毕后回收 ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle));

3.2 通道配置:设置衰减与位宽

创建实例后,通过adc_oneshot_chan_cfg_t(见 adc_oneshot.h)配置要测量的 IO:

  • atten:ADC 衰减档位,取值范围为上文提到的 0 / 2.5 / 6 / 12 dB;
  • bitwidth:原始转换结果位宽。

调用adc_oneshot_config_channel()使配置生效,该函数可多次调用以配置不同通道,驱动会在内部保存每个通道的配置。

adc_oneshot_chan_cfg_t config = { .bitwidth = ADC_BITWIDTH_DEFAULT, .atten = ADC_ATTEN_DB_12, }; ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN0, &config)); ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN1, &config));

3.3 读取转换结果

调用adc_oneshot_read()获取指定通道的原始转换结果:

int adc_raw[2][2]; ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw[0][0])); ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, adc_raw[0][0]);

该函数使用互斥锁避免并发访问硬件,因此不可以在 ISR 上下文调用;当 ADC 正被其他驱动/外设占用时可能返回ESP_ERR_TIMEOUT,此时读到的原始结果无效。

原始结果换算电压的公式:

Vout = Dout × Vmax / Dmax
符号含义
Vout数字输出结果,代表电压
DoutADC 原始数字读数
Vmax最大可测输入模拟电压,与 ADC 衰减相关(参考 TRM "On-Chip Sensor and Analog Signal Processing" 章节)
DmaxADC 原始数字读数最大值,即 2^bitwidth,其中 bitwidth 为配置的通道位宽

若要获得以 mV 为单位的精确电压,推荐使用校准驱动(见本文第五章),或直接使用便捷函数adc_oneshot_get_calibrated_result()——它一步完成"读取原始结果 + 校准为电压",该函数同样声明于 adc_oneshot.h。

3.4 oneshot 模式的其他要点

  • 电源管理:启用CONFIG_PM_ENABLE后,系统空闲时系统时钟频率可能被调整。oneshot 驱动以轮询方式工作,adc_oneshot_read()会持续占用 CPU 直到返回,期间任务不会阻塞,因此读取时时钟频率保持稳定。
  • IRAM Safe:默认情况下所有 oneshot API 不允许在 Cache 禁用时运行(如 Flash 写入/擦除、OTA 期间),否则可能出现Illegal InstructionLoad/Store Prohibited错误。
  • 线程安全adc_oneshot_new_unitadc_oneshot_config_channeladc_oneshot_readadc_oneshot_del_unit均保证线程安全,可在不同 RTOS 任务中直接调用,无需额外加锁。
  • Kconfig 选项CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM控制 ADC 快速读取函数放置在 IRAM 还是 Flash(见 components/esp_adc/Kconfig)。

四、ADC Continuous 模式驱动详解

continuous 模式下,ADC 对一路或多路模拟输入通道执行自动高速采样,结果通过 DMA 高效传输到内存,适用于音频采集、波形监测、电力计量等高频/周期性数据采集场景。

4.1 转换帧(Conversion Frame)与转换结果

continuous 模式以转换帧为单位组织数据:

  • 转换帧(Conversion Frame):一个帧包含多个转换结果,帧大小由adc_continuous_new_handle()按字节配置;
  • 转换结果(Conversion Result):一个结果由多个字节组成,字节数由宏SOC_ADC_DIGI_RESULT_BYTES定义,其结构为adc_digi_output_data_t,包含 ADC 单元、ADC 通道与原始数据。

例如conv_frame_size = 100表示一个转换帧包含100 / SOC_ADC_DIGI_RESULT_BYTES个转换结果。该概念在 adc_continuous.h 头部注释中有完整图示说明。

4.2 资源分配:创建与回收驱动句柄

创建驱动前设置adc_continuous_handle_cfg_t(见 adc_continuous.h):

  • max_store_buf_size:内部缓冲池最大字节数,驱动将转换结果保存到该池;
  • conv_frame_size:转换帧大小(字节),应为SOC_ADC_DIGI_DATA_BYTES_PER_CONV的倍数;
  • flags.flush_pool:当缓冲池满时,自动冲刷旧数据并写入新数据;否则新转换结果将丢失。
adc_continuous_handle_t handle = NULL; adc_continuous_handle_cfg_t adc_config = { .max_store_buf_size = 1024, .conv_frame_size = 256, }; ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config, &handle));

adc_continuous_new_handle()可能因参数非法、内存不足等失败。特殊地,返回ESP_ERR_NOT_FOUND的含义因芯片而异:ESP32 表示 I2S0 外设已被占用,ESP32-S2 表示 SPI3 已被占用,支持 GDMA 的芯片则代表没有空闲的 GDMA 通道。不再使用驱动时调用adc_continuous_deinit()反初始化。

4.3 通道与采样配置

初始化后,通过adc_continuous_config_t配置要采样的 IO(见 adc_continuous.h):

  • pattern_num:使用的 ADC 通道数量;
  • adc_pattern:每个通道的配置列表,类型为adc_digi_pattern_config_t,包含atten(衰减)、channel(通道号)、unit(所属 ADC 单元)、bit_width(原始结果位宽);
  • sample_freq_hz:期望的采样频率(Hz),可用的采样频率范围见soc/soc_caps.h
  • conv_mode:连续转换模式;
  • format:转换输出格式(已标记 deprecated)。

调用adc_continuous_config()使配置生效。若返回ESP_ERR_INVALID_STATE,说明驱动已启动,此时不应再调用该 API。

4.4 启动与停止

ESP_ERROR_CHECK(adc_continuous_start(handle)); // 开始转换 ESP_ERROR_CHECK(adc_continuous_stop(handle)); // 停止转换

4.5 注册事件回调

通过adc_continuous_register_event_callbacks()可将用户函数挂接到驱动 ISR,支持的回调定义于adc_continuous_evt_cbs_t

  • on_conv_done:一个转换帧完成时触发;
  • on_pool_ovf:内部缓冲池已满时触发,此时新转换结果将被丢弃(通常因为adc_continuous_read()读取速度远慢于 ADC 转换速度)。

回调在ISR 上下文中执行,因此回调内不能包含阻塞逻辑。事件数据adc_continuous_evt_data_t提供转换帧缓冲区指针conv_frame_buffer与大小size;注意该缓冲区由驱动自行维护,切勿手动 free。可通过user_data参数向回调传递用户上下文。当启用CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE时,回调及回调调用的函数须放置在 IRAM,涉及的变量也应放在内部 RAM。

4.6 读取与解析转换结果

adc_continuous_start()之后,调用adc_continuous_read()获取转换结果:

  • 可请求读取指定长度的结果;若实际可用结果不足,函数仍会将内部池中的数据搬运到用户缓冲区,实际搬运长度通过out_length返回;
  • 若内部池中暂无结果,函数会阻塞timeout_ms毫秒直到至少产生一个结果,超时仍未产生则返回ESP_ERR_TIMEOUT
  • 若结果填满内部池导致新结果丢失,下次调用将返回ESP_ERR_INVALID_STATE

continuous 模式读出的原始数据需进一步解析为结构化结果。ESP-IDF 提供两种方式:

方式一:adc_continuous_parse_data()手动解析

uint32_t ret_num = 0; esp_err_t ret = adc_continuous_read(handle, result, EXAMPLE_READ_LEN, &ret_num, 0); if (ret == ESP_OK) { adc_continuous_data_t parsed_data[ret_num / SOC_ADC_DIGI_RESULT_BYTES]; uint32_t num_parsed_samples = 0; esp_err_t parse_ret = adc_continuous_parse_data(handle, result, ret_num, parsed_data, &num_parsed_samples); if (parse_ret == ESP_OK) { for (int i = 0; i < num_parsed_samples; i++) { if (parsed_data[i].valid) { ESP_LOGI(TAG, "ADC%d, Channel: %d, Value: %"PRIu32, parsed_data[i].unit + 1, parsed_data[i].channel, parsed_data[i].raw_data); } } } }

注意:raw_data_size必须是SOC_ADC_DIGI_RESULT_BYTES的整数倍,且raw_data缓冲区需足够容纳raw_data_size字节数据;解析函数内置了防缓冲区溢出与整数溢出的边界检查。

方式二:adc_continuous_read_parse()一步读取并解析

adc_continuous_data_t parsed_data[64]; // 用户指定最大样本数 uint32_t num_samples = 0; esp_err_t ret = adc_continuous_read_parse(handle, parsed_data, 64, &num_samples, 1000); if (ret == ESP_OK) { for (int i = 0; i < num_samples; i++) { if (parsed_data[i].valid) { ESP_LOGI(TAG, "ADC%d, Channel: %d, Value: %"PRIu32, parsed_data[i].unit + 1, parsed_data[i].channel, parsed_data[i].raw_data); } } }

解析后的结构体adc_continuous_data_t(见 adc_continuous.h)包含:

  • unit:ADC 单元(ADC_UNIT_1 或 ADC_UNIT_2);
  • channel:ADC 通道号(0-9);
  • raw_data:ADC 原始数据值;
  • valid:数据是否有效。

与 oneshot 模式相同,原始结果换算电压的公式为Vout = Dout × Vmax / Dmax,其中Dmax中的 bitwidth 对应adc_digi_pattern_config_t::bit_width

4.7 IIR 滤波器与 Monitor 监视器

IIR 滤波器:支持SOC_ADC_DIG_IIR_FILTER_SUPPORTED的芯片在 continuous 模式下提供两个 IIR 滤波器。创建时需设置adc_continuous_iir_filter_config_t(包含unitchannelcoeff系数),调用adc_new_continuous_iir_filter()创建,adc_del_continuous_iir_filter()回收。在部分芯片上滤波器按 ADC 单元绑定(SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED),一旦启用会对该单元所有已启用通道滤波,建议使用滤波功能时每单元只启用一个通道,避免滤波结果混合;启用/停用分别调用adc_continuous_iir_filter_enable()/adc_continuous_iir_filter_disable()

Monitor 监视器:支持SOC_ADC_MONITOR_SUPPORTED的芯片可创建监视器(数量见SOC_ADC_DIGI_MONITOR_NUM),对工作通道设置一个或两个阈值,当转换结果超出阈值时在每个采样周期触发中断。配置结构体adc_monitor_config_t包含adc_unitchannelh_threshold(高阈值,不用时置 -1)、l_threshold(低阈值,不用时置 -1)。操作 API 包括adc_continuous_monitor_enable/disableadc_continuous_monitor_register_event_callbacksadc_del_continuous_monitor

monitor 的典型应用是过零检测:由于 ADC 无法直接处理负输入信号,需先通过电路叠加DC 偏置把负信号"平移"进 ADC 量程——例如叠加 1 V 偏置可将 -1 V ~ +1 V 的信号变换为 0 V ~ 2 V。随后设置合适的上下阈值,即可检测输入信号是否逼近零点,从而识别信号相位变化:

adc_monitor_handle_t adc_monitor_handle = NULL; adc_monitor_config_t zero_crossing_config = { .adc_unit = EXAMPLE_ADC_UNIT_1, // 指定要监视的 ADC 单元 .channel = EXAMPLE_ADC_CHANNEL_0, // 指定要监视的 ADC 通道 .h_threshold = 1100, // 高阈值,接近 DC 偏置值,可按需调整 .l_threshold = 900, // 低阈值,接近 DC 偏置值,可按需调整 }; ESP_ERROR_CHECK(adc_new_continuous_monitor(&zero_crossing_config, &adc_monitor_handle)); adc_monitor_evt_cbs_t zero_crossing_cbs = { .on_over_high_thresh = example_on_exceed_high_thresh, .on_below_low_thresh = example_on_below_low_thresh, }; ESP_ERROR_CHECK(adc_continuous_monitor_register_event_callbacks(adc_monitor_handle, &zero_crossing_cbs, NULL)); ESP_ERROR_CHECK(adc_continuous_monitor_enable(adc_monitor_handle)); // ... 使用完毕后停用并删除 ESP_ERROR_CHECK(adc_continuous_monitor_disable(adc_monitor_handle)); ESP_ERROR_CHECK(adc_del_continuous_monitor(adc_monitor_handle));

4.8 continuous 模式的其他要点

  • 电源管理:启用CONFIG_PM_ENABLE后,系统空闲时 APB 时钟频率可能被调整,从而影响连续转换行为。continuous 驱动通过获取ESP_PM_APB_FREQ_MAX类型的电源管理锁来阻止该变化——锁在adc_continuous_start()后获取、adc_continuous_stop()后释放,因此两者必须成对出现,否则电源管理将失效。
  • IRAM Safe:默认所有 continuous API 均非 IRAM-safe。启用CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE后,驱动内部 ISR 处理器变为 IRAM-safe,即使 Cache 被禁用也能将转换结果保存到内部池。
  • 线程安全:continuous 模式 API 不保证线程安全,但驱动提供共享硬件互斥保护。

五、ADC 校准驱动详解

由于不同芯片的实际参考电压存在 1000 mV ~ 1200 mV 的制造偏差,直接解读原始读数会产生较大误差。ADC 校准驱动通过软件修正偏差,输出更精确的结果。

5.1 校准方案(Scheme)的选择与创建

从校准驱动视角看,校准方案创建后得到一个校准句柄adc_cali_handle_t。可使用adc_cali_check_scheme()查询芯片支持的校准方案;若已知支持方案可跳过此步直接调用对应创建函数。芯片支持的方案由宏标识:

  • ADC_CALI_SCHEME_VER_LINE_FITTING(直线拟合):ESP32、ESP32-S2、ESP32-C2;
  • ADC_CALI_SCHEME_VER_CURVE_FITTING(曲线拟合):ESP32-C3、ESP32-S3、ESP32-C6、ESP32-H2、ESP32-C5、ESP32-P4 等。

Line Fitting 方案:配置结构体adc_cali_line_fitting_config_t包含unit_id(原始结果来源 ADC)、atten(所用衰减)、bitwidth(原始结果位宽)。ESP32 上还有default_vref配置项,通常置 0 即可——Line Fitting 方案并不依赖该值;但若板子上未烧录方案所需的 eFuse 位,驱动将依赖该值完成校准。可用adc_cali_scheme_line_fitting_check_efuse()检查 eFuse 位状态:正常为ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP(两点值)或ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF(参考电压值);当为ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF时需设置default_vref

ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting"); adc_cali_line_fitting_config_t cali_config = { .unit_id = unit, .atten = atten, .bitwidth = ADC_BITWIDTH_DEFAULT, }; ESP_ERROR_CHECK(adc_cali_create_scheme_line_fitting(&cali_config, &handle)); // ... 使用完毕后 ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle));

Curve Fitting 方案:配置结构体adc_cali_curve_fitting_config_t同样包含unit_idattenbitwidth,以及为扩展性保留的chan字段。在 ESP32-C3 / ESP32-S3 上,校准只与衰减相关、与通道无关;而在 ESP32-C6 / ESP32-H2 / ESP32-C5 / ESP32-P4 上,校准不仅随衰减变化、还与通道相关,因此chan需填写原始结果来源通道。

ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting"); adc_cali_curve_fitting_config_t cali_config = { .unit_id = unit, .atten = atten, .bitwidth = ADC_BITWIDTH_DEFAULT, }; ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &handle)); // ... 使用完毕后 ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle));

eFuse 相关失败:当创建函数返回ESP_ERR_NOT_SUPPORTED,说明校准方案所需的 eFuse 位未正确烧录。ESP-IDF 的校准方案基于片上特定 ADC 校准 eFuse 位,Espressif 保证这些位在模组制造时已烧录,用户无需自行烧录。若遇到此类错误,请联系官方技术支持渠道。

若想使用自定义校准方案,可参照 components/esp_adc/interface/adc_cali_interface.h 中的函数表adc_cali_scheme_t实现创建函数。

5.2 结果换算:raw → mV

校准特性设置完成后,调用adc_cali_raw_to_voltage()将原始结果转换为以 mV 为单位的校准结果:

int voltage[2][2]; ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_cali_handle, adc_raw[0][0], &voltage[0][0])); ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, voltage[0][0]);

若返回ESP_ERR_INVALID_STATE,说明校准方案句柄尚未创建,需先创建方案句柄(或用adc_cali_check_scheme()确认支持方案)。

注意(ESP32-C2):该校准仅支持ADC_ATTEN_DB_0ADC_ATTEN_DB_12两种衰减。0 dB 下衰减为 0 dB,不支持高于 950 mV 的输入电压;12 dB 下实际衰减为 11 dB,不支持高于 2800 mV 的输入电压。

5.3 线程安全

工厂函数adc_cali_check_scheme()esp_adc_cali_new_scheme()由驱动保证线程安全;其他以adc_cali_handle_t为首参的函数不保证线程安全,应避免从多个任务同时调用。

5.4 降低噪声(Minimize Noise)

ADC 对噪声敏感,可能导致读数偏差较大。根据使用场景,可在使用的 ADC 输入引脚上连接旁路电容(例如 100 nF 陶瓷电容)来抑制噪声;此外多次采样(multisampling)也是一种有效的降噪手段。

上图展示了 ESP32 上通过旁路电容与 64 次多次采样组合后的噪声抑制效果。ESP32 上还可通过 Kconfig 选项裁剪校准代码体积:CONFIG_ADC_CALI_EFUSE_TP_ENABLECONFIG_ADC_CALI_EFUSE_VREF_ENABLECONFIG_ADC_CALI_LUT_ENABLE(若不用 12 dB 衰减下的校准可关闭查找表)。上述校准选项定义于 components/esp_adc/Kconfig。

六、硬件限制与注意事项汇总

芯片限制说明
通用同一 ADC 单元同一时刻只能工作于一种模式(oneshot 或 continuous),驱动已提供保护;RNG 随机数发生器以 ADC 为输入源,ADC 工作时 RNG 随机性下降
差分芯片(SOC_ADC_DIFF_SUPPORTED)单端模式下若以 N 侧通道作为输入接口,其原始数据极性反转(-2 V ~ 2 V 输入对应 N 侧原始码 4393 ~ 0),请使用校准 API 转换
ESP32 / ESP32-S2 / ESP32-S3ADC2 同时被 Wi-Fi 使用,驱动已提供两者间的互斥保护
ESP32-C3ADC2 oneshot 模式因硬件限制不再支持(结果不稳定,见芯片勘误表),可启用CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3强制使用
ESP32-C3 / ESP32-S3ADC2 DMA 功能因硬件限制不再支持,可启用CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3强制使用
ESP32continuous 驱动使用 I2S0 外设作为 DMA FIFO,I2S0 被占用时adc_continuous_new_handle()返回ESP_ERR_NOT_FOUND;ESP32-DevKitC 的 GPIO0 因自动下载电路不可用;ESP-WROVER-KIT 的 GPIO 0/2/4/15 不可用
ESP32-S2continuous 驱动使用 SPI3 外设作为 DMA FIFO,被占用时同样返回ESP_ERR_NOT_FOUND

相关 Kconfig 选项集中在 components/esp_adc/Kconfig:CONFIG_ADC_DISABLE_DAC_OUTPUT(ADC2 使用时默认禁用 DAC 输出)、CONFIG_ADC_ENABLE_DEBUG_LOG等。

七、示例工程与 API 参考

  • examples/peripherals/adc/oneshot_read:演示使用 oneshot 驱动从 GPIO 读取单次 ADC 读数,并调用校准函数获得以 mV 为单位的校准结果;
  • examples/peripherals/adc/continuous_read:演示在开发板上使用 continuous 模式(DMA)从 GPIO 引脚持续读取 ADC 数据。

两个示例均为可直接编译运行的完整工程,是学习两种驱动模式配置流程的最佳起点。

完整 API 参考(类型、配置结构体与函数文档)可进一步阅读:

  • oneshot 模式 API(实现见 adc_oneshot.c)
  • continuous 模式 API(实现见 adc_continuous.c)
  • 校准驱动 API(实现见 adc_cali.c)

总结

ESP-IDF 的 ADC 驱动体系以"原始数据 + 校准换算"为设计核心:oneshot 模式以极简 API 覆盖低频按需采样场景,continuous 模式借助 DMA、转换帧、事件回调、IIR 滤波与阈值监视器等机制支撑高频连续采集,而校准驱动则通过 Line Fitting / Curve Fitting 两种方案将制造偏差修正到 mV 级精度。实际选型时,只需根据采样频率需求确定模式、依据信号幅度选择衰减档位,并牢记各芯片特有的硬件限制与电源管理、IRAM-safe 等约束,即可在 ESP32 全系列芯片上稳定、精确地完成模拟信号采集。

【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 20:23:21

Oracle EBS R12总账模块实施要点:从科目结构到月结流程全解析

做Oracle ERP EBS R12项目的人&#xff0c;十有八九是先跟总账&#xff08;GL&#xff09;打交道的。GL是整个EBS财务体系的中枢&#xff0c;AP、AR、FA、成本模块的数据最终都会汇总到GL&#xff0c;月末结账、出报表、做预算、管理多组织账套&#xff0c;全都绕不开这个模块。…

作者头像 李华
网站建设 2026/9/15 20:21:21

滑模控制MATLAB实现:边界层与趋近律的工程化抖振抑制

简介&#xff1a;本资源是一套面向自动化、控制工程专业本科生及初学者的滑模变结构控制&#xff08;SMC&#xff09;MATLAB仿真源码包&#xff0c;专为课程设计与期末大作业打造&#xff0c;解决理论理解难、代码实现无从下手、仿真调试耗时等典型痛点。压缩包共359个文件&…

作者头像 李华
网站建设 2026/9/15 20:20:54

抖音视频批量去水印保存:douyin-downloader 三步上手指南

抖音视频批量去水印保存&#xff1a;douyin-downloader 三步上手指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback su…

作者头像 李华
网站建设 2026/9/15 20:19:20

CSV转Fluent Profile完整指南:格式、转换与导入避坑

做CFD的人多半都遇到过这个需求&#xff1a;手里有一份实测数据或者上游软件导出的结果&#xff0c;格式是CSV&#xff0c;想把它作为Fluent里的Profile&#xff08;数据表&#xff09;喂给边界条件或初始条件用。我最早接触这件事是在处理一个通风管道入口的速度分布&#xff…

作者头像 李华