(九)ESP32-S3之ADC

ADC 简介

生活中接触到的大多数信息是醉着时间连续变化的物理量,如声音、温度、压力等。表达
这些信息的电信号,称为模拟信号(Analog Signal)。为了方便存储、处理,在计算机系统中,都是数字 0 和 1 信号,将模拟信号(连续信号)转换为数字信号(离散信号)的器件就叫模数转换器(Analog-to-Digital Convert,ADC)。
ADC 转换器可分为:并行比较型 A/D 转换器(FLASH ADC)、逐次比较型 A/D 转换器(SAR
ADC)和双积分式 A/D 转换器(Double Integral ADC)。
A/D 转换过程通常为 4 步:采样、保持、量化和编码,如下图所示
在这里插入图片描述
采样:把时间连续变化的信号变换为时间离散的信号。
保持:保持采样信号,使有充分时间转换为数字信号。
量化:把采样保持电路的输出信号用单位量化电压的整数倍表示。
编码:把量化的结果用二进制代码表示。
采样和保持通常是在采样-保持电路中完成,量化和编码通常在 ADC 数字编码电路中完成

ESP32-S3 ADC

ESP32-S3 集成了两个 12 位 SARADC,ADC1 和 ADC2,支持 20 个模拟通道输入。这 20 个
模拟通道输入对应着具体的 IO,并不是随意的 IO 都有模拟输入功能,具备模拟输入功能的引
脚如下表所示。
在这里插入图片描述
SP32-S3 的 ADC 模块的分辨率为 12 位,所以 AD转换后的值范围为 0~4095。由于 ESP32-
S3 的工作电压为 3.3V,所以当 AD 值为 4095 时,对应的电压为 3.3V;当 AD 值为 0 时,对应的电压为 0V。对于 AD 值和电压值,这里就会有一个简单的关系,如下所示
在这里插入图片描述

ADC 函数解析

ESP-IDF 提供了一套 API 来配置 ADC。要使用此功能,需要导入必要的头文件:

#include " esp_adc_cal.h"
#include " driver/adc"

接下来,作者将介绍一些常用的 ESP32-S3 中的 ADC 函数,这些函数的描述及其作用如下
配置 ADC该函数用于配置 ADC 各项参数,其函数原型如下所示:

esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config);

该函数使用 adc_digi_pattern_config_t 以及 adc_digi_configuration_t 类型的结构体变量传入,
该结构体的定义如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

读取 ADC 原始数据
该函数用于读取 ADC 原始数据,其函数原型如下所示:

int adc1_get_raw(adc1_channel_t channel);

ADC 驱动解析

IDF 版 14_adc 例程中,作者在 14_adc \components\BSP 路径下新增了一个 ADC 文件夹,
分别用于存放 adc.c、adc.h 这两个文件。其中,adc.h 文件负责声明 ADC 相关的函数和变量,而adc.c 文件则实现了 ADC 的驱动代码。下面,我们将详细解析这两个文件的实现内容。
adc.h

/* ADC 采集通道定义 */
#define ADC_ADCX_CHY ADC1_CHANNEL_7

adc.c

**
* @brief 初始化 ADC
* @param 无
* @retval 无
*/
void adc_init(void)
{
adc_digi_pattern_config_t adc1_digi_pattern_config; /* ADC1 配置句柄 */
/* ADC1 初始化句柄 */
 adc_digi_configuration_t adc1_init_config;
 
 /* 配置 ADC1 */
 adc1_digi_pattern_config.atten = ADC_ATTEN_DB_11; /* 配置 ADC 衰减程度 */
 adc1_digi_pattern_config.channel = ADC_ADCX_CHY; /* 配置 ADC 通道 */
 

上面的代码中可以看出,ADC 的初始化函数中,配置了 ADC1 通道 7。
ADC 驱动中,获取 ADC 转换结果的函数,如下所示:

/**
* @brief 获取 ADC 转换且进行均值滤波后的结果
* @param ch : 通道号, 0~9
* @param times : 获取次数
* @retval 通道 ch 的 times 次转换结果平均值
*/
uint32_t adc_get_result_average(uint32_t ch, uint32_t times)
{
 uint32_t temp_val = 0;
 uint8_t t;
 for (t = 0; t < times; t++) /* 获取 times 次数据 */
 {
 temp_val += adc1_get_raw(ch);
 vTaskDelay(5);
 }
 return temp_val / times; /* 返回平均值 */
}

上函数用于获取 ADC 转换结果的函数,函数 adc_get_result_averagr()则是多次调用
adc1_get_raw()获取多次 ADC 的转换结果,然后进行均值滤波.
CMakeLists.txt
打开本实验 BSP 下的 CMakeLists.txt 文件,其内容如下所示:

set(src_dirs
 ADC
 IIC
 LCD
 LED
 SPI
 XL9555)
set(include_dirs
 ADC
 IIC
 LCD
 LED
 SPI
 XL9555)
set(requires
 driver
 esp_adc)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)

打开 main/main.c 文件,该文件定义了工程入口函数,名为 app_main。该函数代码如下

i2c_obj_t i2c0_master;
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
 uint16_t adcdata;
 float voltage;
 esp_err_t ret;
 ret = nvs_flash_init(); /* 初始化 NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES 
|| ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
 {
 ESP_ERROR_CHECK(nvs_flash_erase());
 ret = nvs_flash_init();
 }
 led_init(); /* 初始化 LED */
 i2c0_master = iic_init(I2C_NUM_0); /* 初始化 IIC0 */
 spi2_init(); /* 初始化 SPI2 */
 xl9555_init(i2c0_master); /* 初始化 XL9555 */
 lcd_init(); /* 初始化 LCD */
 adc_init(); /* 初始化 ADC */
 lcd_show_string(30, 50, 200, 16, 16, "ESP32", RED);
 lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
 lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
 lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH7_VAL:", BLUE);
 lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH7_VOL:0.000V", BLUE);
 while(1)
 {
 adcdata = adc_get_result_average(ADC_ADCX_CHY, 10);
 /* 显示 ADC 采样后的原始值 */
 lcd_show_xnum(134, 110, adcdata, 5, 16, 0, BLUE); 
 voltage = (float)adcdata * (3.3 / 4096);/* 获取计算后的带小数的实际电压值 */
 adcdata = voltage; /* 赋值整数部分给 adcx 变量 */
 lcd_show_xnum(134, 130, adcdata, 1, 16, 0, BLUE);/* 显示电压值的整数部分 */
 voltage -= adcdata;/* 把已经显示的整数部分去掉,留下小数部分 */
 voltage *= 1000; /* 小数部分乘以 1000 */
 lcd_show_xnum(150, 130, voltage, 3, 16, 0x80, BLUE); /* 显示小数部分 */
 LED_TOGGLE(); /* LED 翻转函数 */
 vTaskDelay(100);
 }
}

从上面的代码中可以看出,在进行完包括 ADC 的所有初始化工作后,便不断地获取 ADC1
通道 7 进行 10 次转换后经过均值滤波后的结果,并将该原始值显示在 LCD 上,同时还通过该
电压的原始值计算出了电压的模拟量,并在 LCD 上进行显示。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值