5. ESP32_ADC(Arduino)

本文介绍了ESP32集成的12位逐次逼近式ADC模块,包括ADC1和ADC2的通道配置,以及如何使用Arduino的analogRead函数进行电压测量。还展示了光照电压采样和利用ADC控制LED亮度的实训案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ADC模数转换

ESP32集成了12位的逐次逼近式ADC,分别为ADC1模块ADC2模块,共支持18个模拟输入通道:

  • ADC1模块:8个通道,32~39
  • ADC2模块:10个通道,0,2,4,12 ~ 15,25 ~ 15;部分引脚和WIFI模块共用

ESP32ADC参考电压为内部提供的 V R E F V_{REF} VREF,不同芯片, V R E F V_{REF} VREF不同,中位数是1.1V
默认情况下,ADC的模拟信号输入范围是: 0~1.1V。如果要测量高于1.1V的电压,
则要对输入电压进行衰减ESP32提供了4种衰减倍数(以ESP32-S2为例) :

  • 0dB:不衰减, 可测量输入电压范围: 0~750mv,参考电压: 1.1V
  • 2.5dB:可测量输入电压范围: 0~1050mv, 参考电压: 1 .35V
  • 6dB:可测量输入电压范围: 0~1300mv, 参考电压: 2.2V
  • 11dB:可测量输入电压范围: 0~2600mv, 参考电压: 3.3V

在Arduino中,只需要调用analogRead()方法,即可完成ESP32的转换和读取
请添加图片描述

API

ADC的转换和读取函数

uint16_t analogRead(uint8_t pin);

analogRead() 是一个用于读取pin引脚模拟输入值的函数。默认情况下ADC分辨率12位它返回一个介于 0(完全关闭)4095(完全打开) 之间的整数,衰减倍数为11dB,模拟输入的范围0-3.3v,参考电压可取3.3v

  • **pin:**指定引脚编号
// 读取模拟输入值
int sensorValue = analogRead(analogPin);
// 将读取到的值转换为电压值
float voltage = sensorValue * (3.3 / 4095);

实训案例

光照电压采样和换算

#include <Arduino.h> 

#define ain 35 // 定义模拟输入引脚为35

uint16_t adc_value = 0; // 定义一个16位无符号整数变量用于存储ADC采样值
float adc_voltage = 0.0; // 定义一个浮点数变量用于存储ADC电压值

void read_adc() // 定义一个函数用于读取ADC采样值和电压值
{
  adc_value = analogRead(ain); // 从模拟输入引脚读取采样值并存储到adc_value变量中
  adc_voltage = adc_value * (3.3 / 4095); // 根据采样值计算电压值并存储到adc_voltage变量中

  Serial.printf("采样值:%d 电压值:%.2f", adc_value, adc_voltage); // 通过串口打印采样值和电压值
  Serial.println(); // 换行
  delay(500); // 延时500毫秒
}

void setup()
{
  Serial.begin(115200); // 设置串口波特率为115200
}

void loop() 
{
  read_adc(); // 调用read_adc函数读取ADC采样值和电压值
}

效果如下:
请添加图片描述
在这里插入图片描述

光照电压动态控制灯光亮度

#include <Arduino.h>

#define d2 2 // 定义引脚d2为数字输出引脚
#define ain 35 // 定义模拟输入引脚ain为35

uint16_t adc_value = 0; // 定义一个16位无符号整数变量adc_value,用于存储ADC采样值

void Init_PWM() // 初始化PWM函数
{
  ledcSetup(1, 128, 12); // 设置PWM通道1的频率为128Hz,占空比为12%
  ledcAttachPin(d2, 1); // 将PWM通道1与引脚d2连接
}

void adc_set_pwm() // 设置PWM值的函数
{
  adc_value = analogRead(ain); // 读取模拟输入引脚ain的采样值,并存储到adc_value变量中
  ledcWrite(1, adc_value); // 将PWM通道1的占空比设置为adc_value
  Serial.println(adc_value); // 通过串口打印adc_value的值
  delay(100); // 延时100毫秒
}

void setup() 
{
  Init_PWM(); // 调用初始化PWM函数
  Serial.begin(115200); // 设置串口波特率为115200
}

void loop() 
{
  adc_set_pwm(); // 调用设置PWM值的函数
}

效果如下:
请添加图片描述
请添加图片描述

### 使用ESP32ADC与DMA在Arduino平台上的实现 #### 环境配置 确保已安装必要的开发环境。对于ESP32,在Arduino环境中只需安装所需的库并加载草图到开发板即可[^1]。 #### ADC简介 模拟数字转换器(Analog-to-Digital Converter, ADC)用于将物理世界的连续信号转化为离散数值表示形式以便于微控制器处理。ESP32内置有高精度多通道ADC模块,支持单次采样模式以及扫描模式下的自动循环读取功能。 #### DMA技术概述 直接存储器访问(Direct Memory Access, DMA)允许外设绕过CPU直接同内存交互,从而减少处理器负担并加快数据传输速度。通过启用DMA特性可以显著提升批量数据操作性能,尤其是在持续监控传感器输入场景下显得尤为重要。 #### 实现方案 为了使能ESP32上基于DMA机制工作的ADC接口,需利用特定API函数完成初始化设置: ```cpp #include <driver/adc.h> // 配置参数结构体定义... adc_dma_config_t config; config.channel = ADC_CHANNEL_0; // 设置使用的ADC通道号 config.dma_desc_num = 8; // 描述符数量影响缓冲区大小 config.intr_priority = 7; // 中断优先级设定 config.max_transfer_size = 4096; // 单次最大转移字节数量限制 // 初始化DMA驱动程序实例化对象 adc_dma_handle_t adc_dma; // 安装并启动DMA引擎关联至指定ADC单元 esp_err_t ret = adc_dma_install(&config,&adc_dma); if(ret != ESP_OK){ Serial.println("Failed to install ADC DMA driver"); } ``` 上述代码片段展示了如何创建一个带有适当属性集的新DMA会话,并将其绑定给选定的ADC资源。值得注意的是,这里调用了`adc_dma_install()`方法来执行实际硬件层面的操作;如果返回值不是成功状态,则表明存在问题需要排查解决。 当准备就绪之后就可以安排周期性的测量任务了——这通常涉及到编写回调函数以响应每次完整的样本集合事件: ```cpp void IRAM_ATTR on_adc_dma_completed(void *priv_data){ size_t bytes_transferred = *(size_t*)priv_data; static uint32_t sample_count=0; // 处理接收到的数据包... while(bytes_transferred--){ float voltage = (float)(*(((uint16_t*)(adc_dma->buffer))+sample_count)) / 4095.0f * 3.3f; Serial.printf("Sample %d Voltage:%.3fv\n",++sample_count,voltage); if(sample_count >= MAX_SAMPLES){break;} } } // 注册中断服务例程(ISR),每当一组新的样品可用时触发该ISR ret = adc_dma_register_cb(adc_dma,on_adc_dma_completed,(void*)&bytes_read); if(ret != ESP_OK){ Serial.println("Failed to register callback function."); } ``` 此部分实现了异步通知机制,使得应用程序能够在后台无缝接收到来自ADC设备的信息更新而无需主动轮询查询端口状态变化情况。一旦满足预设条件(比如达到一定数目),则停止进一步监听直至下次重启为止。 最后一步就是激活整个链路使之进入运行态: ```cpp // 开始一次新序列化的AD变换过程 ret = adc_dma_start_continuous_sampling(adc_dma,ADC_UNIT_1,FREQUENCY_HZ,BUFFER_SIZE_IN_BYTES); if(ret != ESP_OK){ Serial.println("Failed to start continuous sampling."); }else{ Serial.println("Continuous Sampling Started..."); } ``` 这段脚本负责开启不间断的数据流获取流程,其中指定了目标ADC组件编号、期望频率及内部暂存区域尺寸等关键要素作为入参传递进去供底层逻辑解析使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宁子希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值