ESP32S3基于espidf ADC使用

ops/2025/2/12 21:20:34/

ESP32S3基于espidf ADC使用


  • 官方在线文档介绍模数转换器:https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32s3/api-reference/peripherals/adc_oneshot.html
  • 🔖espidf版本:v5.4
  • 模数转换器 (ADC)转换方式:
    • 模数转换器 (ADC) 单次转换模式驱动
    • 模数转换器 (ADC) 连续转换模式驱动
    • 模数转换器 (ADC) 带校准驱动
  • ESP32-S3 功能框图
    在这里插入图片描述

ESP32S3 ADC介绍

ESP32-S3 内置了两个 12 位的 SAR ADC,可测量最多来自 20 个管脚的模拟信号。

  • SAR ADC概图
    在这里插入图片描述
主要特性
  • 支持 12 位采样分辨率
    • 支持采集最多 20 个管脚上的模拟电压

  • RTC ADC1/2 控制器:
    – 支持单次转换
    – 支持在低功耗模式下工作,如 Deep-sleep
    – 可由 ULP 协处理器配置

  • DIG ADC1 控制器:
    – 配有多通道扫描控制模块,支持多通道扫描模式
    – 提供模式控制模块,支持单 SAR ADC 采样模式
    – 在多通道扫描模式下,支持自定义扫描通道顺序
    – 提供两个滤波器,滤波系数可配
    – 支持阈值监控,采样值大于设置的高阈值或小于设置的低阈值将产生中断
    – 支持 DMA。

  • SAR ADC 的主要元件与连接情况见图
    在这里插入图片描述
    在这里插入图片描述

  • SAR ADC 模块主要包括以下部分:
    • SAR ADC1:可对 10 个通道进行电压检测;
    • SAR ADC2:可对 10 个通道进行电压检测;

  • SAR ADC 的信号输入
    在这里插入图片描述
    在这里插入图片描述

ADC 转换和衰减

SAR ADC 转换模拟信号时,转换分辨率(12 位)电压范围为 0 mV ~ Vref。其中,Vref 为 SAR ADC 内部参考电
压,出厂设定为 1100 mV。因此,转换结果 (data) 可以使用以下公式转换成模拟电压输出 Vdata:
在这里插入图片描述

  • ADC 经硬件校准和 软件校准后的结果如表下表 所示。如需更高的精度,可选用其他方法自行校准。
    在这里插入图片描述
  • ✨在使用ADC测量模拟输入电压时,被测电压信号,阈值最好不要超过3V。不然精度会比上表所述低。
  • 针对esp32型号,只有在未启动Wi-Fi 驱动程序下,才能使用 ADC2。
    在这里插入图片描述
  • esp32S3 SAR ADC2的数字控制器无法工作

ESP32-S3 SAR ADC2 的数字控制器(即DIGADC2控制器)可能收到错误的采样启动信号,导致控制器进入无法工作的状态。

  • 无变通方法。建议使用RTC控制器来控制SAR ADC2。

🔰编译器不同版本和ADC驱动程序差异

  • 在当前所使用的v5.4版本下,所调用的ADC驱动头文件:
    adc_cali.hadc_cali_scheme.hadc_continuous.hadc_oneshot.h
  • 在旧版本中,所包含的头文件:
#include "driver/adc.h"

当前版本(v5.4)下,部分旧版本的API程序还是可以使用,可能在未来某个版本中会全部移除。有些API已经不支持了,仍继续使用的话,程序运行可能会报错。并且编译时会报警告信息:

#warning "legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively"

📘数转换器 (ADC) 单次转换模式驱动


  • 所需包含的头文件:
#include "esp_adc/adc_oneshot.h"
  • ADC 驱动代码
  • 模数转换器 (ADC) 单次转换模式驱动可以参考:v5.4\esp-idf\examples\peripherals\adc\oneshot_read
#include <stdio.h>
#include "esp_adc/adc_oneshot.h"#define ADC1_CHANNEL ADC_CHANNEL_6  // 使用 ADC1 通道 6 (GPIO 6)
#define ADC_ATTEN    ADC_ATTEN_DB_12  // 衰减值
#define ADC_BITWIDTH ADC_BITWIDTH_12  // 位宽void app_main(void) {// 初始化 ADC 单元adc_oneshot_unit_handle_t adc1_handle;adc_oneshot_unit_init_cfg_t init_config = {.unit_id = ADC_UNIT_1,  // 使用 ADC1};ESP_ERROR_CHECK(adc_oneshot_unit_init(&init_config, &adc1_handle));// 配置 ADC 通道adc_oneshot_chan_cfg_t channel_config = {.atten = ADC_ATTEN,  // 衰减值.bitwidth = ADC_BITWIDTH,  // 位宽};ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC1_CHANNEL, &channel_config));// 读取 ADC 值while (1) {int adc_raw_value = 0;ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC1_CHANNEL, &adc_raw_value));printf("ADC Raw Value: %d\n", adc_raw_value);// 延时 1 秒vTaskDelay(pdMS_TO_TICKS(1000));}// 释放资源(此代码不会执行到此处,仅为示例)ESP_ERROR_CHECK(adc_oneshot_unit_deinit(adc1_handle));
}

在这里插入图片描述

📗模数转换器 (ADC) 校准驱动

#include <stdio.h>
#include "driver/gpio.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_oneshot.h"
//#include "esp_adc/adc_oneshot_unit.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_err.h"#define TAG "ADC_CAL"#define DEFAULT_VREF    1100  // 默认内部参考电压 (mV)
#define NO_OF_SAMPLES   64    // 采样次数
#define ADC1_CHANNEL ADC_CHANNEL_6  // 使用 ADC1 通道 6 (GPIO 6)
#define ADC_ATTEN    ADC_ATTEN_DB_12  // 衰减值
#define ADC_BITWIDTH ADC_BITWIDTH_12  // 位宽void app_main(void) {// 初始化 ADC 单元adc_oneshot_unit_handle_t adc1_handle;adc_oneshot_unit_init_cfg_t init_config = {.unit_id = ADC_UNIT_1,  // 使用 ADC1};ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));// 配置 ADC 通道adc_oneshot_chan_cfg_t channel_config = {.atten = ADC_ATTEN,  // 衰减值.bitwidth = ADC_BITWIDTH,  // 位宽};ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC1_CHANNEL, &channel_config));// 初始化校准方案adc_cali_handle_t adc_cali_handle = NULL;adc_cali_curve_fitting_config_t cali_config = {.unit_id = ADC_UNIT_1,.atten = ADC_ATTEN,.bitwidth = ADC_BITWIDTH,};esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle);if (ret == ESP_OK) {printf("Calibration scheme created successfully\n");} else {printf("Failed to create calibration scheme\n");return;}while (1) {int adc_raw_value = 0;ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC1_CHANNEL, &adc_raw_value));printf("ADC Raw Value: %d\n", adc_raw_value);// 将原始值转换为电压int voltage = 0;if (adc_cali_raw_to_voltage(adc_cali_handle, adc_raw_value, &voltage) == ESP_OK) {printf("ADC Raw Value: %d\tVoltage: %dmV\n", adc_raw_value, voltage);} else {printf("Failed to convert raw value to voltage\n");}vTaskDelay(pdMS_TO_TICKS(1000));}// 释放校准方案资源//  ESP_ERROR_CHECK(adc_cali_delete_scheme(adc_cali_handle));// 释放 ADC 单元资源(此代码不会执行到此处,仅为示例)//  ESP_ERROR_CHECK(adc_oneshot_unit_deinit(adc1_handle));
}

在这里插入图片描述

📒模数转换器 (ADC) 连续转换模式驱动

  • 可以参考例程:v5.4\esp-idf\examples\peripherals\adc\continuous_read
  • ✨连续转换模式需要注意,输出数据格式,只能选择类型2:ADC_DIGI_OUTPUT_FORMAT_TYPE2,否则,使用类型1,烧录后会报错:
    在这里插入图片描述
单通道转换模式和连续多通道转换模式共用驱动实现程序
#include <stdio.h>
#include "driver/gpio.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_err.h"#define TAG "ADC_CAL"#define DEFAULT_VREF    1100  // 默认内部参考电压 (mV)
#define NO_OF_SAMPLES   64    // 采样次数
#define ADC1_CHANNEL ADC_CHANNEL_6  // 使用 ADC1 通道 6 (GPIO 6)
#define ADC_ATTEN    ADC_ATTEN_DB_12  // 衰减值
#define ADC_BITWIDTH ADC_BITWIDTH_12  // 位宽
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1  // 使用 ADC1 单通道模式
#define DMA_BUFFER_SIZE 8                  // DMA 缓冲区大小
#define SAMPLE_RATE   10000                   // 采样率 (Hz)//#define oneshot    1		//oneshot模式启用
#define continuous 1		//连续转换模式启用void app_main(void) {
#ifdef oneshot// 初始化 ADC 单元adc_oneshot_unit_handle_t adc1_handle;adc_oneshot_unit_init_cfg_t init_config = {.unit_id = ADC_UNIT_1,  // 使用 ADC1};ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));// 初始化 ADC 单元adc_oneshot_unit_handle_t adc1_handle;adc_oneshot_unit_init_cfg_t init_config = {.unit_id = ADC_UNIT_1,  // 使用 ADC1};ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));// 配置 ADC 通道adc_oneshot_chan_cfg_t channel_config = {.atten = ADC_ATTEN,  // 衰减值.bitwidth = ADC_BITWIDTH,  // 位宽};ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC1_CHANNEL, &channel_config));#elif continuous// 初始化 ADC 连续模式句柄adc_continuous_handle_t adc_handle = NULL;adc_continuous_handle_cfg_t handle_cfg = {.max_store_buf_size = DMA_BUFFER_SIZE,  // DMA 缓冲区大小.conv_frame_size = DMA_BUFFER_SIZE,     // 每帧数据大小};ESP_ERROR_CHECK(adc_continuous_new_handle(&handle_cfg, &adc_handle));// 配置 ADC 通道adc_digi_pattern_config_t adc_pattern_ch[2] = {{.atten = ADC_ATTEN,.channel = ADC_CHANNEL_6,.unit = ADC_UNIT_1,.bit_width = ADC_BITWIDTH,},{.atten = ADC_ATTEN,.channel = ADC_CHANNEL_7,.unit = ADC_UNIT_1,.bit_width = ADC_BITWIDTH,},};// 配置 ADC 连续模式adc_continuous_config_t adc_config = {.pattern_num = 2,  // 使用 2 个通道.adc_pattern = adc_pattern_ch,.sample_freq_hz = SAMPLE_RATE,  // 采样率.conv_mode = ADC_CONV_MODE,     // 转换模式.format = ADC_DIGI_OUTPUT_FORMAT_TYPE2,  // 输出格式};ESP_ERROR_CHECK(adc_continuous_config(adc_handle, &adc_config));// 启动连续采样ESP_ERROR_CHECK(adc_continuous_start(adc_handle));ESP_LOGI(TAG, "ADC continuous mode started");// 读取采样数据uint8_t buffer[DMA_BUFFER_SIZE] = {0};#endifwhile (1) {#ifdef oneshotint adc_raw_value = 0;ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC1_CHANNEL, &adc_raw_value));printf("ADC Raw Value: %d\n", adc_raw_value);// 将原始值转换为电压int voltage = 0;if (adc_cali_raw_to_voltage(adc_cali_handle, adc_raw_value, &voltage) == ESP_OK) {printf("ADC Raw Value: %d\tVoltage: %dmV\n", adc_raw_value, voltage);} else {printf("Failed to convert raw value to voltage\n");}#elif continuous// 读取采样数据uint32_t ret_num = 0;esp_err_t ret = adc_continuous_read(adc_handle, buffer, DMA_BUFFER_SIZE, &ret_num, 0);if (ret == ESP_OK) {ESP_LOGI(TAG, "Read %"PRIu32" bytes of data", ret_num);// 处理采样数据(例如打印或存储)// for (int i = 0; i < ret_num; i += 2) {  // 假设每个采样点占 2 字节//     uint16_t adc_value = (buffer[i + 1] << 8) | buffer[i];//     printf("ADC Value: %d\n", adc_value);// }// 解析 TYPE2 格式的数据for (int i = 0; i < ret_num; i += 2) {  // 每个采样点占 2 字节uint16_t adc_value = (buffer[i + 1] << 8) | buffer[i];uint8_t unit = (adc_value >> 12) & 0x0F;  // 提取单元标识uint16_t raw_data = adc_value & 0x0FFF;   // 提取 12 位原始数据printf("Unit: %d, Raw Data: %d\n", unit, raw_data);}} else {ESP_LOGE(TAG, "Failed to read data: %d", ret);}
#endifvTaskDelay(pdMS_TO_TICKS(1000));}// 单采样释放校准方案资源//  ESP_ERROR_CHECK(adc_cali_delete_scheme(adc_cali_handle));// 释放 ADC 单元资源(此代码不会执行到此处,仅为示例)//  ESP_ERROR_CHECK(adc_oneshot_unit_deinit(adc1_handle));// 连续采样停止采样并释放资源// ESP_ERROR_CHECK(adc_continuous_stop(adc_handle));// ESP_ERROR_CHECK(adc_continuous_deinit(adc_handle));// ESP_LOGI(TAG, "ADC continuous mode stopped");
}
  • 🔖CMakeLists.txt:
idf_component_register(SRCS "main.c"INCLUDE_DIRS "."REQUIRES driver esp_adc)

http://www.ppmy.cn/ops/157864.html

相关文章

【STM32系列】利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计IIR数字滤波器可以看这里&#xff1a;利用MATLAB配合ARM-DSP库设计IIR数字滤波器&#xff08;保姆级教程&#xff09; 前言 本篇文章将介绍如何利用MATLAB与STM32的ARM-DSP库相结合&#xff0c;简明易懂地实现FIR低通滤波器的设计与应用。文章重点不在…

Android车机DIY开发之软件篇(十二) AOSP12下载编译

Android车机DIY开发之软件篇(十二) AOSP12下载编译 sudo apt-get update sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib gmultilib libc6-dev-i386 lib32ncurses5-dev libx11-dev lib32z-dev ccache libgl1-mesa-…

基于Python的人工智能驱动基因组变异算法:设计与应用(下)

3.3.2 数据清洗与预处理 在基因组变异分析中,原始数据往往包含各种噪声和不完整信息,数据清洗与预处理是确保分析结果准确性和可靠性的关键步骤。通过 Python 的相关库和工具,可以有效地去除噪声、填补缺失值、标准化数据等,为后续的分析提供高质量的数据基础。 在基因组…

Maven在idea中的使用

介绍 什么是maven&#xff1f; Maven是apache旗下的一个开源项目&#xff0c;是一款管理和构建java项目的工具。 maven作用&#xff1f; 方便快捷的管理项目依赖和资源&#xff08;jar包&#xff09;&#xff0c;避免版本冲突问题 。提供标准、统一的项目结构。标准跨平台&…

爬虫工程师分享:获取京东商品详情SKU数据的技术难点与攻破方法

在电商数据领域&#xff0c;京东商品详情页的SKU数据是许多爬虫工程师的目标。这些数据包含了商品的价格、库存、规格等关键信息&#xff0c;对于市场分析、价格监控等应用场景至关重要。然而&#xff0c;获取这些数据并非易事&#xff0c;京东作为国内电商巨头&#xff0c;其反…

蓝桥杯备考之AB 数对

P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 这道题解法一就是用set来做&#xff0c;先把每个数存在map里&#xff0c;然后枚举B加上C看是不是在数列里面 解法二就是我们的二分&#xff0c;我们数列的顺序是不会影响最终的结果的&#xff0c;我们可以先对数列进行一下排序…

【鸿蒙开发】第二十四章 AI -Natural Language Kit(自然语言理解服务)

目录 1 简介 2 约束与限制 3. 分词 3.1 适用场景 3.2 约束与限制 3.3 开发步骤 3.4 开发实例 4 实体抽取 4.1 适用场景 4.2 约束与限制 4.3 开发步骤 4.4 开发实例 1 简介 Natural Language Kit&#xff08;自然语言理解服务&#xff09;提供了多项文本语义理解相…

自学人工智能大模型,满足7B模型的训练和微调以及推理,预算3万,如何选购电脑

如果你的预算是 3万元人民币&#xff0c;希望训练和微调 7B 参数规模的人工智能大模型&#xff08;如 LLaMA、Mistral 等&#xff09;&#xff0c;你需要一台高性能的深度学习工作站。在这个预算范围内&#xff0c;以下是推荐的配置&#xff1a; 1. 关键硬件配置 (1) GPU (显卡…