单片机/MCUwilliam hill官网
直播中

jf_85110202

未满1年用户 284经验值
擅长:嵌入式技术 开发板 仪表仪器 单片机
私信 关注
[文章]

《DNESP32S3使用指南-IDF版_V1.6》 第二十四章 ADC实验

第二十四章 ADC实验

本章介绍使用ESP32-S3模数转换器(ADC)进行带通道的电压采集。通过本章的学习,读者将学习到单通道ADC的使用。
本章分为如下几个小节:
24.1 ADC简介
24.2 硬件设计
24.3 程序设计
24.4 下载验证


24.1 ADC介绍
24.1.1 ADC简介
生活中接触到的大多数信息是醉着时间连续变化的物理量,如声音、温度、压力等。表达这些信息的电信号,称为模拟信号(Analog Signal)。为了方便存储、处理,在计算机系统中,都是数字01信号,将模拟信号(连续信号)转换为数字信号(离散信号)的器件就叫模数转换器(Analog-to-Digital ConvertADC)。
        ADC转换器可分为:并行比较型A/D转换器(FLASH ADC)逐次比较型A/D转换器(SAR ADC)和双积分式A/D转换器(Double Integral ADC)
A/D转换过程通常为4步:采样、保持、量化和编码,如下图所示。
第二十四章 ADC实验437.png
24.1.1.1 A/D转换过程图
        采样:把时间连续变化的信号变换为时间离散的信号。
        保持:保持采样信号,使有充分时间转换为数字信号。
        量化:把采样保持威廉希尔官方网站 的输出信号用单位量化电压的整数倍表示。
        编码:把量化的结果用二进制代码表示。
        采样和保持通常是在采样-保持威廉希尔官方网站 中完成,量化和编码通常在ADC数字编码威廉希尔官方网站 中完成。
24.1.2 ESP32-S3ADC介绍
ESP32-S3集成了两个12SAR ADCADC1ADC2,支持20个模拟通道输入。这20个模拟通道输入对应着具体的IO,并不是随意的IO都有模拟输入功能,具备模拟输入功能的引脚如下表所示。
第二十四章 ADC实验726.png
24.1.2.1 具备模拟输入功能的引脚
ESP32-S3ADC模块的分辨率为12位,所以AD转换后的值范围为0~4095。由于ESP32-S3的工作电压为3.3V,所以当AD值为4095时,对应的电压为3.3V;当AD值为0时,对应的电压为0V。对于AD值和电压值,这里就会有一个简单的关系,如下所示。
第二十四章 ADC实验883.png
24.2 硬件设计
24.2.1 例程功能
1. 本章实验功能简介:使用ADC采集通道7IO8)上面的电压,在SPILCD模块上面显示ADC转换值以及换算成电压后的电压值。在P3端口中,使用短路帽将AINRV1排针连接,使得IO8连接到电位器上,然后将ADC采集到的数据和转换后的电压值在SPILCD屏中显示。用户可以通过调节电位器的旋钮改变电压值。LED闪烁,提示程序运行。
2. LED闪烁,指示程序正在运行。
24.2.2 硬件资源
1. LED
LED - IO1
2. XL9555
IIC_SDA-IO41
IIC_SCL-IO42
3. SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SETLCD_DC相连)
PWR- IO1_3XL9555
RST- IO1_2XL9555
4. ADC
ADC1_CHANNEL_7
24.2.3 原理图
ADC属于ESP32-S3内部资源,实际上我们只需要软件设置就可以正常工作,另外还需要将待测量的电压源连接到ADC通道上,以便ADC测量。本实验,我们通过ADC1的通道7IO8)来采集外部电压值,开发板有一个电位器,可调节的电压范围是:0~3.3V。我们可以通过跳线帽将IO8与电位器连接,如下图所示:
第二十四章 ADC实验1457.png
24.2.3.1 IO8(对应AIN排针)与电位器引脚示意
使用杜邦线将ADCRV1排针连接好后,并下载程序后,就可以用螺丝刀调节电位器变换多种电压值进行测量。
有的朋友可能还想测量其它地方的电压值,我们只需要1根杜邦线,一端接到AIN排针上,另外一端就接你要测试的电压点。一定要保证测试点的电压在0~3.3V的电压范围,否则可能烧坏我们的ADC,甚至是整个主控芯片。
24.3 程序设计
24.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图: 第二十四章 ADC实验1757.png
24.3.1.1 ADC实验程序流程图
24.3.2 ADC函数解析
ESP-IDF提供了一套API来配置ADC。要使用此功能,需要导入必要的头文件:
#include " esp_adc_cal.h"
#include " driver/adc"
接下来,作者将介绍一些常用的ESP32-S3中的ADC函数,这些函数的描述及其作用如下:
1配置ADC
该函数用于配置ADC各项参数,其函数原型如下所示:
esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config);
该函数的形参描述,如下表所示:
形参
描述
config
指向ADC配置结构体的指针
需自行定义,并根据ADC的配置参数填充结构体中的成员变量
24.3.2.1 函数adc_digi_controller_configure()形参描述
返回值:ESP_OK表示配置成功。其他表示配置失败。
该函数使用adc_digi_pattern_config_t以及adc_digi_configuration_t类型的结构体变量传入,该结构体的定义如下所示:
结构体
成员变量
可选参数
adc_digi_pattern_config_t
atten:
配置ADC衰减程度adc_atten_t结构体为索引
ADC_ATTEN_DB_0,输入电压0-1.1V
ADC_ATTEN_DB_2_5,输入电压0-1.5V
ADC_ATTEN_DB_6,输入电压0-2.2V
ADC_ATTEN_DB_11,输入电压0-3.3V
channel:
配置ADC通道adc1_channel_t结构体为索引
ADC1_CHANNEL_0 ,
ADC1_CHANNEL_1,   
ADC1_CHANNEL_2,   
ADC1_CHANNEL_3,   
ADC1_CHANNEL_4,   
ADC1_CHANNEL_5,   
ADC1_CHANNEL_6,   
ADC1_CHANNEL_7,   
unit:
配置ADC单元adc_unit_t结构体为索引
ADC_UNIT_1
ADC_UNIT_2
bit_width:
配置ADC位宽adc_bitwidth_t结构体为索引
ADC_BITWIDTH_DEFAULT
ADC_BITWIDTH_9
ADC_BITWIDTH_10
ADC_BITWIDTH_11
ADC_BITWIDTH_12
ADC_BITWIDTH_13
24.3.2.2 adc_digi_pattern_config_t结构体参数值描述
结构体
成员变量
可选参数
adc_digi_configuration_t
adc_pattern:
配置将要使用的每个ADC参数
无,该参数为结构体指针,当adc_digi_pattern_config_t结构体成员配置完成后,以指针的方式将参数传递至adc_pattern这一成员中
24.3.2.3 adc_digi_configuration_t结构体参数值描述
完成上述结构体参数配置之后,可以将结构传递给 adc_digi_controller_configure () 函数,用以实例化ADC
2,读取ADC原始数据
该函数用于读取ADC原始数据,其函数原型如下所示:
int adc1_get_raw(adc1_channel_t channel);
该函数的形参描述,如下表所示:
形参
描述
channel
ADC通道
24.3.2.4 函数adc1_get_raw()形参描述
返回值:其他值表示ADC原始数值,-1表示读取失败。
24.3.3 ADC驱动解析
IDF14_adc例程中,作者在14_adc \components\BSP路径下新增了一个ADC文件夹,分别用于存放adc.cadc.h这两个文件。其中,adc.h文件负责声明ADC相关的函数和变量,而adc.c文件则实现了ADC的驱动代码。下面,我们将详细解析这两个文件的实现内容。
1adc.h文件
/* ADC采集通道定义 */
#define ADC_ADCX_CHY   ADC1_CHANNEL_7
2adc.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通道 */
    adc1_digi_pattern_config.unit = ADC_UNIT_1;                         /* 配置ADC单元 */
adc1_digi_pattern_config.bit_width = ADC_BITWIDTH_12;        /* 配置ADC位宽 */
/* 配置将要使用的每个ADC参数 */
    adc1_init_config.adc_pattern = &adc1_digi_pattern_config;
    adc_digi_controller_configure(&adc1_init_config);                /* 配置ADC1 */
}
从上面的代码中可以看出,ADC的初始化函数中,配置了 ADC1通道7
ADC驱动中,获取ADC转换结果的函数,如下所示:
/**
* @brief       获取ADC转换且进行均值滤波后的结果
* @param       ch                : 通道号, 0~9
* @param       times        : 获取次数
* @retval      通道chtimes次转换结果平均值
*/
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的转换结果,然后进行均值滤波。
24.3.4 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)
上述的红色ADC驱动以及esp_adc依赖库需要由开发者自行添加,以确保ADC驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了ADC驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。
24.3.5 实验应用代码
打开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上进行显示。
24.4 下载验证
在完成编译和烧录操作后,可以看到LCD上实时刷新显示着ADC1通道7IO8引脚)采集到电压的数字量和模拟量,此时可以通过杜邦线给IO8引脚接入不同的电压值(注意共地,且输入电压不能超过3.3V,否则可能损坏开发板),可以看到LCD上显示的电压数字量和模拟量也随之改变。
第二十四章 ADC实验7767.png
24.4.1 SPI LCD显示效果图

更多回帖

发帖
×
20
完善资料,
赚取积分