SOC-ESP32S3部分:19-ADC模数转换

article/2025/8/7 7:46:19

飞书文档https://x509p6c8to.feishu.cn/wiki/XycAwmO6Niitdtka1RAcclYfnvf

ESP32-S3 集成了两个 12 位 SAR ADC,共支持 20 个模拟通道输入。

SAR ADC 管脚通过 IO MUX 与 GPIO1 ~ GPIO20、RTC_GPIO1 ~ RTC_GPIO20、触摸传感器接口、UART 接口、SPI 接口、以及 USB_D- 和 USB_D+ 管脚复用。

所以这里有一个点需要注意,并不是所有IO都支持ADC功能,只有特定IO支持。

在ESP32S3中如何使用ADC功能呢?分为以下几步

  1. 创建ADC单元实例
  2. 配置ADC通道
  3. 读取转换结果
  4. 创建校准方案
  5. 转换为实际电压值

创建 ADC 单元实例

adc_oneshot_new_unit 函数用于创建一个新的 ADC 单次采样单元,并根据提供的配置进行初始化。

esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, adc_oneshot_unit_handle_t *out_handle);
参数说明
const adc_oneshot_unit_init_cfg_t *init_config
指向 adc_oneshot_unit_init_cfg_t 结构体的指针,该结构体包含 ADC 单次采样模式的初始化配置信息。adc_oneshot_unit_handle_t *out_handle
输出参数,用于返回新创建的 ADC 单次采样单元的句柄。通过这个句柄可以对 ADC 进行后续操作,如配置通道、启动转换等。

adc_oneshot_unit_init_cfg_t用于配置 ADC(模数转换器)的单次采样模式。

typedef struct {adc_unit_t unit_id;            adc_oneshot_clk_src_t clk_src; adc_ulp_mode_t ulp_mode;       
} adc_oneshot_unit_init_cfg_t;adc_unit_t unit_id
表示使用的 ADC 单元。
ADC选择,用于表示不同的 ADC 单元,可选ADC_UNIT_1 和 ADC_UNIT_2 等,分别代表不同的 ADC 硬件单元。adc_oneshot_clk_src_t clk_src
选择 ADC 的时钟源。设置为 0 时,驱动程序将使用默认时钟源adc_ulp_mode_t ulp_mode
设置是否支持 ADC 在超低功耗模式下工作。

使用参考:

adc_oneshot_unit_init_cfg_t init_config1 = {.unit_id = ADC_UNIT_1,.ulp_mode = ADC_ULP_MODE_DISABLE,
};adc_oneshot_unit_handle_t adc1_handle;
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));

配置ADC通道参数

创建 ADC 单元实例后,通过adc_oneshot_config_channel 函数配置 ADC 单次采样模式下的特定通道。

esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, const adc_channel_t *channel, const adc_oneshot_chan_cfg_t *chan_cfg);
参数说明
adc_oneshot_unit_handle_t handle:
ADC 单次采样单元的句柄,由 adc_oneshot_new_unit 函数创建并返回。const adc_channel_t *channel:
指向 adc_channel_t 类型的指针,表示要配置的 ADC 通道(例如 ADC1_CHANNEL_0、ADC2_CHANNEL_1 等)。const adc_oneshot_chan_cfg_t *chan_cfg:
指向 adc_oneshot_chan_cfg_t 结构体的指针

设置 adc_oneshot_chan_cfg_t 配置 ADC IO 以测量模拟信号,具体如下:

typedef struct {adc_atten_t atten;       ///< 衰减等级adc_bitwidth_t bitwidth; ///< 位宽
} adc_oneshot_chan_cfg_t;字段说明
atten
含义:表示 ADC 输入信号的衰减等级。
ADC 模块在测量高电压时需要适当的衰减以防止输入过载。常见的衰减等级包括:
ADC_ATTEN_DB_0: 无衰减(适用于低电压信号)
ADC_ATTEN_DB_2_5: 2.5 dB 衰减
ADC_ATTEN_DB_6: 6 dB 衰减
ADC_ATTEN_DB_12: 12 dB 衰减bitwidth
含义:表示 ADC 转换结果的位宽。位宽决定了 ADC 转换结果的精度和范围。常见的位宽包括:
ADC_BITWIDTH_DEFAULT: 默认位宽(通常为 12 位)
ADC_BITWIDTH_9: 9 位
ADC_BITWIDTH_10: 10 位
ADC_BITWIDTH_11: 11 位
ADC_BITWIDTH_12: 12 位

使用参考:

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

读取转换结果

完成上述配置后,ADC 即可测量来自配置好的 ADC 通道的模拟信号。调用 adc_oneshot_read 可以获取 ADC 通道的原始转换结果。

esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, const adc_channel_t *channel, int32_t *out_raw);
参数说明
adc_oneshot_unit_handle_t handle:
ADC 单次采样单元的句柄,由 adc_oneshot_new_unit 函数创建并返回。const adc_channel_t *channel:
指向 adc_channel_t 类型的指针,表示要读取的 ADC 通道。int32_t *out_raw:
输出参数,用于返回 ADC 转换后的原始数据值。

使用参考

static int adc_ch2_raw;
static int adc_ch3_raw;
adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, &adc_ch2_raw);
ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, ADC_CHANNEL_0, adc_ch2_raw);

创建校准方案

为了让采集的数据更准确,我们可以使用官方提供的校准算法,ESP-IDF 提供的 ADC 校准方案基于芯片上某些与 ADC 校准相关的 eFuse 位的值。乐鑫模组已在出厂时完成烧录,无需用户额外烧录。

创建校准方案使用adc_cali_create_scheme_curve_fitting函数

创建校准方案
esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_config_t *config, adc_cali_handle_t *ret_handle);
参数说明
const adc_cali_curve_fitting_config_t *config:
指向 adc_cali_curve_fitting_config_t 结构体的指针,包含曲线拟合所需的配置信息。adc_cali_handle_t *ret_handle:
指向 adc_cali_handle_t 类型的指针,用于存储创建的 ADC 校准方案的句柄。// 定义并初始化曲线拟合校准配置结构体
adc_cali_curve_fitting_config_t cali_config = {.unit_id = unit,          // 设置 ADC 单元(例如 ADC_UNIT_1 或 ADC_UNIT_2).atten = atten,           // 设置 ADC 输入信号的衰减等级(例如 ADC_ATTEN_DB_11).bitwidth = ADC_BITWIDTH_DEFAULT, // 设置 ADC 转换结果的位宽,默认为 12 位
};
// 创建曲线拟合校准方案,并将结果存储在 handle 中
ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &handle));

使用参考:

// 定义并初始化曲线拟合校准配置结构体,结构体的数据和上述ADC采集保持一致
adc_cali_curve_fitting_config_t cali_config = {.unit_id = ADC_UNIT_1,    .atten = ADC_ATTEN_DB_12,.chan = ADC_CHANNEL_2,.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &handle));

转换为实际电压值

adc_cali_raw_to_voltage 函数用于将 ADC 转换后的原始数据值转换为实际的电压值。

esp_err_t adc_cali_raw_to_voltage(adc_cali_handle_t handle, int raw, int *out_voltage);
参数说明
adc_cali_handle_t handleADC :
校准句柄,由 adc_cali_create_scheme_curve_fitting创建函数返回。int rawADC:
转换后的原始数据值。int *out_voltage :
输出参数,用于返回校准后的电压值(单位:毫伏,mV)。

使用参考:

int voltage;
// 调用 adc_cali_raw_to_voltage 进行转换
esp_err_t ret = adc_cali_raw_to_voltage(cali_handle, adc_ch2_raw, &voltage);

最终参考

我们需要采集底板的滑动电阻器的值,从原理图可以看到,滑动电阻器是接到GPIO1上的

GPIO1支持的ADC控制器和通道是固定的,可从课程开始的介绍图中看到,对应ADC1 通道0

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"const static char *TAG = "EXAMPLE";// 定义ADC1通道0对应的GPIO引脚
#define EXAMPLE_ADC1_UNIT ADC_UNIT_1
#define EXAMPLE_ADC1_CHAN0 ADC_CHANNEL_0 // ADC1 CH0 对应板卡的滑动电阻器GPIO0
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12 // 设置衰减为12dB// 定义全局变量存储ADC原始数据和校准后的电压值
static int adc_raw_ch0;
static int voltage_ch0;// 初始化ADC校准
static bool example_adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle)
{esp_err_t ret = ESP_FAIL;bool calibrated = false;adc_cali_curve_fitting_config_t cali_config = {.unit_id = unit,          // ADC单元编号.chan = channel,          // ADC通道编号.atten = atten,           // 衰减值.bitwidth = ADC_BITWIDTH_DEFAULT, // 位宽};// 创建曲线拟合校准方案ret = adc_cali_create_scheme_curve_fitting(&cali_config, out_handle);if (ret == ESP_OK){calibrated = true;}return calibrated;
}void app_main(void)
{//-------------ADC1 Init---------------//adc_oneshot_unit_handle_t adc1_handle;adc_oneshot_unit_init_cfg_t init_config1 = {.unit_id = EXAMPLE_ADC1_UNIT, // 设置ADC单元为ADC1};// 初始化ADC1单元ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));//-------------ADC1 Config---------------//adc_oneshot_chan_cfg_t config = {.atten = EXAMPLE_ADC_ATTEN, // 设置衰减值为12dB.bitwidth = ADC_BITWIDTH_DEFAULT, // 设置位宽为默认值};// 配置ADC1通道0ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN0, &config));//-------------ADC1 Calibration Init---------------//adc_cali_handle_t adc1_cali_chan0_handle = NULL;// 初始化ADC1通道0的校准bool do_calibration1_chan0 = example_adc_calibration_init(EXAMPLE_ADC1_UNIT, EXAMPLE_ADC1_CHAN0, EXAMPLE_ADC_ATTEN, &adc1_cali_chan0_handle);while (1){// 读取ADC1通道0的原始数据ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw_ch0));ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", EXAMPLE_ADC1_UNIT + 1, EXAMPLE_ADC1_CHAN0, adc_raw_ch0);// 如果通道0进行了校准,将原始数据转换为电压值if (do_calibration1_chan0){ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw_ch0, &voltage_ch0));ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", EXAMPLE_ADC1_UNIT + 1, EXAMPLE_ADC1_CHAN0, voltage_ch0);}// 延迟1秒vTaskDelay(pdMS_TO_TICKS(1000));}
}

烧录后,使用螺丝刀滑动电阻器,就可以看到读取的ADC值变化啦


http://www.hkcw.cn/article/AOsUoFuYNf.shtml

相关文章

默克微生物培养基选择指南

微生物学研究需要能在实验室提供各种不同种类的细菌、酵母或病毒。诸如发酵、蛋白质和疫苗生产的大规模过程需要大量处于生理活性状态的细菌。因此&#xff0c;针对各种应用需要有能提供适当的生化环境并保持微生物所有特征的合适的营养培养基。 任何微生物培养基都应包括营养…

移动安全Android——解决APP抓包证书无效问题

问题 通过Burpsuite和ProxyPin进行代理抓包Android APP的时候发现虽然已经正确添加了用户证书&#xff0c;但是还是会出现SSL握手错误&#xff0c;证书无效问题。这是因为Android 7 以上版本APP默认不信任用户证书&#xff0c;只信任系统证书&#xff0c;所以需要将用户证书移动…

【数据库】数据库恢复技术

数据库恢复技术 实现恢复的核心是使用冗余&#xff0c;也就是根据冗余数据重建不正确数据。 事务 事务是一个数据库操作序列&#xff0c;是一个不可分割的工作单位&#xff0c;是恢复和并发的基本单位。 在关系数据库中&#xff0c;一个事务是一条或多条SQL语句&#xff0c…

【学习笔记】深度学习-梯度概念

一、定义 梯度向量不仅表示函数变化的速度&#xff0c;还表示函数增长最快的方向 二、【问】为什么说它表示方向&#xff1f; 三、【问】那在深度学习梯度下降的时候&#xff0c;还要判断梯度是正是负来更新参数吗&#xff1f; 假设某个参数是 w&#xff0c;损失函数对它的…

【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用

【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用 文章目录 前言正文配置环境下载源码配置环境变量测试运行修改点说明实际运行情况 参考 前言 本文用来记录 xCoreSDK-Python的调用使用1。 正文 配置环境 配置开发环境&#xff0c;这里使用conda做python环境管理&…

深入浅出网络分析与故障检测工具

目录 网络故障检测工具&#xff1a;别只靠“Ping 不通” 实战组合拳&#xff1a;分析 检测 问题闭环 四、选择工具的几个建议 五、总结&#xff1a;工具是手段&#xff0c;思维才是核心 在如今这个“数据就是生命线”的时代&#xff0c;网络的稳定性和性能直接决定着企业…

使用Haproxy搭建Web群集

目录 1&#xff0c;Haproxy简介 1&#xff0c;核心功能与特点 二&#xff0c;搭建haproxy群集 1&#xff0c;准备工作 2&#xff0c;修改haproxy的配置文件 3&#xff0c;准备网站 4&#xff0c;配置日志 5&#xff0c;验证 1&#xff0c;Haproxy简介 HAProxy 是一款高…

Elasticsearch的写入流程介绍

Elasticsearch 的写入流程是一个涉及 分布式协调、分片路由、数据同步和副本更新 的复杂过程,其设计目标是确保数据一致性、可靠性和高性能。以下是写入流程的详细解析: 一、写入流程总览 二、详细步骤解析 1. 客户端请求路由 请求入口:客户端(如 Java 客户端、REST API)…

记录一次apisix上cros配置跨域失败的问题

安全要求不允许跨域请求&#xff0c;但是业务侧由于涉及多个域名&#xff0c;并且需要共享cookie&#xff0c;所以需要配置跨域。 在apisix上配置了cors如下。 结果安全漏扫还是识别到了跨域请求的漏洞。 调试了cors.lua的插件脚本&#xff0c;发现apisix上是如果不在allowOri…

VSCode无法转到定义python源码(ctrl加单击不跳转)

已经尝试的方案&#xff1a; 1.确保对应python环境正确激活 在 VSCode 中&#xff0c;打开命令面板&#xff08;CtrlShiftP&#xff09;&#xff0c;输入并选择 Python: Select Interpreter&#xff0c;然后从列表中选择正确的 Python 解释器。 2.重新卸载Python插件再重新安装…

会议室钥匙总丢失?换预约功能的智能门锁更安全

在企业日常运营中&#xff0c;会议室作为重要的沟通与协作场所&#xff0c;其管理效率与安全性直接影响着企业的运作顺畅度。然而&#xff0c;传统会议室管理方式中钥匙丢失、管理不便等问题频发&#xff0c;给企业带来了不少困扰。近期&#xff0c;某企业引入了启辰智慧预约系…

漫画Android:事件分发的过程是怎样的?

当用户触摸屏幕时&#xff0c;硬件层会捕获触摸信号&#xff0c;并将其转化为内核事件。 Android系统会通过InputManagerService和WindowManagerService等服务将这些事件包装成MotionEvent对象&#xff0c;并将其传递给Activity的dispatchTouchEvent()方法中&#xff0c;Activi…

【算法提升】分组 day_tow

1.分组 1.1 解析 个人认为这题最难的点在于如何想到使用二分的算法来解题。 正向求解&#xff1a;就是去看每一组中需要分多少个人&#xff0c;但是这样求解代码我根本写不出来。 所以根据正难则反的思想&#xff0c;我们可以从最终结果去倒推。 枚举最终的分配结果中&#xff…

【笔记】Suna 部署之 Supabase 数据库 schema 暴露操作

#工作记录 一、前置信息 在 Suna 部署过程中&#xff0c;Supabase 数据库设置已完成&#xff08;✅ Supabase database setup completed &#xff09;&#xff0c;但需要手动在 Supabase 平台暴露basejump模式&#xff08;schema&#xff09;。 Suna 部署过程中&#xff0c;S…

【Linux 学习计划】-- 进程状态 | 进程运行、阻塞和挂起的本质 | 并行、并发与进程切换 | 进程优先级

目录 进程状态 五状态进程模型 运行、就绪状态的本质 阻塞状态的本质 挂起状态 并行与并发 进程切换 进程优先级 结语 进程状态 进程状态的本质是什么&#xff1f; 首先我们知道&#xff0c;在操作系统中&#xff0c;进程是需要被管理起来的&#xff0c;具体则是用一…

自证式推理训练:大模型告别第三方打分的新纪元

1. 传统验证体系的困境与技术跃迁的必然性 1.1 传统验证器的局限性 现有强化学习框架依赖显式验证器对答案进行二值化判定&#xff0c;这种模式在数学、代码等可验证领域表现优异。某厂内部数据显示&#xff0c;传统R1-Zero方法在代码生成任务中准确率达92%&#xff0c;但切换…

《操作系统真相还原》——加载器

显存 将上一章的中断输出&#xff0c;变为显存输出 加载器 使用mbr引导程序从磁盘中加载loader程序。 MBR %include "boot.inc" SECTION MBR vstart0x7c00 mov ax,cs mov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax;cl…

Spring Boot 应用中实现配置文件敏感信息加密解密方案

Spring Boot 应用中实现配置文件敏感信息加密解密方案 背景与挑战 &#x1f6a9;一、设计目标 &#x1f3af;二、整体启动流程 &#x1f504;三、方案实现详解 ⚙️3.1 配置解密入口&#xff1a;EnvironmentPostProcessor3.2 通用解密工具类&#xff1a;EncryptionTool 四、快速…

前端实现图片压缩:基于 HTML5 File API 与 Canvas 的完整方案

在 Web 开发中,处理用户上传的图片时,前端压缩可以有效减少服务器压力并提升上传效率。本文将详细讲解如何通过<input type="file">实现图片上传,结合 Canvas 实现图片压缩,并实时展示压缩前后的图片预览和文件大小对比。 一、核心功能架构 我们将实现以…

用wireshark抓了个TCP通讯的包

昨儿个整理了下怎么用wireshark抓包&#xff0c;链接在这里&#xff1a;捋捋wireshark 今天打算抓个TCP通讯的包试试&#xff0c;整体来说比较有收获&#xff0c;给大家汇报一下。 首先就是如何搞到可以用来演示TCP通讯的客户端、服务端&#xff0c;问了下deepseek&#xff0c;…