ESP32 ADC采集实战:精准读取传感器信号
本文介绍了ESP32的ADC功能实现方法。ESP32内置两个12位SAR ADC(ADC1和ADC2),支持多通道模拟信号采集。文章详细说明了ADC的基础特性,包括通道数量、分辨率、输入电压范围等限制条件。重点阐述了ADC配置的5个核心步骤,并提供了基于ESP-IDF的完整代码示例,展示了如何初始化ADC通道、配置参数、读取数据并进行电压转换。文中还包含关键细节说明,如通道与GPIO对应关系、衰减
ESP32 内置了 2 个 12 位 SAR ADC(ADC1 和 ADC2),支持多个模拟输入通道,可用于采集外部模拟信号(如传感器电压、电位器等)。ADC 功能的实现需通过 ESP-IDF 提供的 API 配置通道参数(如衰减、分辨率)、读取原始值并转换为实际电压。以下是详细的实现步骤和代码示例。
一、ESP32 ADC 基础特性
- 通道数量:ADC1 有 8 个通道(GPIO32~GPIO39),ADC2 有 10 个通道(GPIO0、GPIO2、GPIO4、GPIO12GPIO15、GPIO25GPIO27);
- 分辨率:支持 9~12 位(默认 12 位,分辨率越高,精度越高但采样速度略慢);
- 输入电压范围:通过“衰减(attenuation)”配置,默认 0dB 对应 0~1.1V,最高 11dB 可支持 0~3.9V(但 ESP32 GPIO 最大耐压 3.3V,实际输入需≤3.3V);
- 限制:ADC2 与 Wi-Fi 共用硬件资源,启用 Wi-Fi 时可能无法使用 ADC2 通道(建议优先使用 ADC1 通道)。
二、ADC 配置核心步骤
- 选择通道:根据硬件连接选择 ADC1 或 ADC2 的通道(优先 ADC1 以避免 Wi-Fi 冲突);
- 配置衰减:根据输入电压范围设置衰减(如测量 0~3.3V 信号需用 11dB 衰减);
- 配置分辨率:设置采样分辨率(如 12 位,对应 0~4095 的原始值);
- 校准(可选但推荐):使用 ESP32 内置的校准功能,提高电压转换精度;
- 读取并转换:读取原始 ADC 值,通过校准参数转换为实际电压。
三、完整代码实现(基于 ESP-IDF v4.4+)
以下代码以“读取 ADC1 通道 0(GPIO36)的电压”为例,实现连续采样并打印结果,包含校准功能。
1. 头文件与宏定义
#include <stdio.h>
#include "esp_adc_cal.h"
#include "driver/adc.h"
#include "esp_log.h"
// 日志标签
static const char *TAG = "esp32_adc";
// ADC 配置参数
#define ADC_CHANNEL ADC1_CHANNEL_0 // 选择 ADC1 通道 0(对应 GPIO36)
#define ADC_ATTEN ADC_ATTEN_DB_11 // 衰减 11dB(支持 0~3.9V 输入,实际≤3.3V)
#define ADC_WIDTH ADC_WIDTH_BIT_12 // 12 位分辨率(0~4095)
// 校准类型(优先使用 eFuse 校准,无则用默认参数)
#define DEFAULT_VREF 1100 // 默认参考电压(mV),若无 eFuse 校准则使用
static esp_adc_cal_characteristics_t adc_chars;
2. ADC 初始化函数
初始化 ADC 通道,配置衰减、分辨率,并进行校准:
static void adc_init(void) {
// 检查是否支持 eFuse 校准(提高精度)
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
ADC_UNIT_1, // ADC 单元(ADC1)
ADC_ATTEN, // 衰减配置
ADC_WIDTH, // 分辨率
DEFAULT_VREF, // 默认参考电压
&adc_chars // 校准参数结构体
);
// 打印校准类型
if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
ESP_LOGI(TAG, "使用 eFuse VREF 校准");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
ESP_LOGI(TAG, "使用 eFuse 两点校准");
} else {
ESP_LOGI(TAG, "使用默认参考电压(%dmV)", DEFAULT_VREF);
}
// 配置 ADC 通道(ADC1 通道 0)
adc1_config_width(ADC_WIDTH); // 设置分辨率
adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN); // 设置衰减
}
3. ADC 读取与电压转换函数
读取原始 ADC 值,并通过校准参数转换为实际电压(mV):
static uint32_t adc_read_voltage(void) {
// 读取原始 ADC 值(多次采样取平均,减少噪声)
uint32_t adc_raw = 0;
const int sample_count = 10; // 采样次数
for (int i = 0; i < sample_count; i++) {
adc_raw += adc1_get_raw(ADC_CHANNEL); // 读取 ADC1 原始值
}
adc_raw /= sample_count; // 平均值
// 转换为电压(mV),使用校准后的参数
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_raw, &adc_chars);
ESP_LOGI(TAG, "原始值:%d,电压:%dmV", adc_raw, voltage);
return voltage;
}
4. 主函数调用
void app_main(void) {
// 初始化 ADC
adc_init();
// 循环读取 ADC 值(间隔 1 秒)
while (1) {
adc_read_voltage();
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
}
}
四、代码说明与关键细节
1. 通道与 GPIO 对应关系
ADC1 通道对应的 GPIO 如下(可直接使用):
| ADC1 通道 | GPIO 编号 |
|---|---|
| ADC1_CHANNEL_0 | GPIO36 |
| ADC1_CHANNEL_1 | GPIO37 |
| ADC1_CHANNEL_2 | GPIO38 |
| ADC1_CHANNEL_3 | GPIO39 |
| ADC1_CHANNEL_4 | GPIO32 |
| ADC1_CHANNEL_5 | GPIO33 |
| ADC1_CHANNEL_6 | GPIO34 |
| ADC1_CHANNEL_7 | GPIO35 |
2. 衰减与电压范围对应
根据输入信号电压选择衰减(确保输入≤3.3V):
| 衰减配置 | 理论测量范围(V) | 实际建议范围(V) |
|---|---|---|
| ADC_ATTEN_DB_0 | 0 ~ 1.1 | 0 ~ 1.0 |
| ADC_ATTEN_DB_2_5 | 0 ~ 1.5 | 0 ~ 1.4 |
| ADC_ATTEN_DB_6 | 0 ~ 2.2 | 0 ~ 2.0 |
| ADC_ATTEN_DB_11 | 0 ~ 3.9 | 0 ~ 3.3(GPIO 上限) |
3. 校准的重要性
ESP32 的 ADC 存在一定非线性误差,通过 esp_adc_cal_characterize() 函数可利用芯片内部的 eFuse 校准数据(如 VREF 参考电压)优化转换精度:
- 若芯片支持 eFuse 校准(多数新款 ESP32),会自动使用校准数据;
- 若无 eFuse 数据,使用
DEFAULT_VREF(1100mV)作为参考,精度略低。
4. 噪声处理
ADC 采样易受电磁干扰,可通过以下方式降低噪声:
- 多次采样取平均:如代码中使用 10 次采样平均值,平滑波动;
- 硬件滤波:在输入引脚串联 100Ω 电阻 + 并联 100nF 电容,滤除高频噪声;
- 避免强干扰源:远离 Wi-Fi 天线、电机等强干扰设备。
5. ADC2 与 Wi-Fi 的冲突处理
若需使用 ADC2 通道且同时启用 Wi-Fi,需在读取 ADC 前暂停 Wi-Fi,读取后恢复:
// ADC2 读取示例(需配合 Wi-Fi 暂停)
#include "esp_wifi.h"
uint32_t adc2_read_voltage(adc2_channel_t channel) {
uint32_t adc_raw;
// 暂停 Wi-Fi
esp_wifi_pause();
// 读取 ADC2 原始值
adc2_get_raw(channel, ADC_WIDTH, &adc_raw);
// 恢复 Wi-Fi
esp_wifi_resume();
// 转换为电压
return esp_adc_cal_raw_to_voltage(adc_raw, &adc_chars);
}
五、常见问题与解决方案
-
读数为 0 或 4095(最大值):
- 检查输入电压是否超出所选衰减的范围(如 0dB 衰减接 3.3V 会导致读数饱和);
- 确认 GPIO 引脚与 ADC 通道对应正确。
-
读数波动大:
- 增加采样次数取平均;
- 增加硬件滤波电路;
- 远离干扰源。
-
ADC2 读数失败(返回 -1):
- 检查是否启用了 Wi-Fi,需暂停 Wi-Fi 后再读取;
- 确认 ADC2 通道未被其他外设占用(如某些 GPIO 同时支持其他功能)。
总结
ESP32 实现 ADC 功能的核心是:配置通道参数(衰减、分辨率)→ 校准 → 读取并转换电压。通过优先使用 ADC1 通道、合理设置衰减、增加采样平均,可实现稳定可靠的模拟信号采集,适用于传感器数据读取、电压监测等场景。
更多推荐



所有评论(0)