学习笔记04"/>
[ESP32]学习笔记04
Analog-to-Digital Converter(模数转换器)的使用
今天我们学习ESP32提供的ADC外设的使用,ESP32的每个ADC单元都支持两种模式,单次读取和连续读取(DMA),本次实验我们采取单次读取的方式来获取模拟量并用万用表测量电压验证实验的准确性。本次实验采用VSCode进行代码编辑,后续会介绍VSCode搭建ESP32开发环境的方法。
在开始编程前请仔细阅读乐鑫官网给出的ESP-IDF编程指南
链接: ESP-IDF编程指南.
目录
- Analog-to-Digital Converter(模数转换器)的使用
- 查看乐鑫提供的API指南
- 一、配置ADC单次捕获模式
- 二、进行void ADC_Init(void)函数的编写
- 1.引入头文件
- 2.编写初始化函数
- 3.使用int adc1_get_raw(adc1_channel_t channel)进行数据读取
查看乐鑫提供的API指南
首先我们需要去了解精度和电压衰减这两个概念。
简单来说精度就是模数转换器转换的数据宽度,比如说8bit的数据宽度,准换成数字量后最大值也就是满电压的数字量为255,那么为了提高测量的精度,就要提高数据宽度,在乐鑫的API中一共定义了5种数据宽度:10bit~13bit供我们使用,具体应该使用哪种数据宽度,需要根据需求和限制来确定。电压衰减则是通过更改电压衰减增益来扩大测量范围,简单可理解为设置电压衰减来配置ADC的基准电压,我们知道在使用STM32系列新品时,ADC的基准电压是通过外部输入电压来确定,一般为3.3V,在乐鑫ESP32系列芯片中,为我们提供了4中电压衰减增益,来设置4种不同的基准电压,以获取更广的测量范围。
一、配置ADC单次捕获模式
ADC单次捕获数据的模式初始化非常简单,只需要两个函数就可以完成:
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
我们可以查看形参的声明:
typedef enum {
#if CONFIG_IDF_TARGET_ESP32ADC_WIDTH_BIT_9 = 0, /*!< ADC capture width is 9Bit. */ADC_WIDTH_BIT_10 = 1, /*!< ADC capture width is 10Bit. */ADC_WIDTH_BIT_11 = 2, /*!< ADC capture width is 11Bit. */ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit. */
#elif SOC_ADC_MAX_BITWIDTH == 12ADC_WIDTH_BIT_12 = 3, /*!< ADC capture width is 12Bit. */
#elif SOC_ADC_MAX_BITWIDTH == 13ADC_WIDTH_BIT_13 = 4, /*!< ADC capture width is 13Bit. */
#endifADC_WIDTH_MAX,
} adc_bits_width_t;
可以看到这是关于数据宽度的枚举,那么我们需要填入设置数据宽度的函数参数可在此枚举当中选择,通过预编译指令我们可以发现,对于使用ESP32作为目标设备的,可以使用9bit~12bit的数据宽度,对于目标设备的ADC最大数据宽度为12的也可以使用12bit的数据宽度。在这里我使用的是ESP32-S2,所以只能使用13bit的数据宽度。
#if CONFIG_IDF_TARGET_ESP32
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
typedef enum {ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */ADC1_CHANNEL_MAX,
} adc1_channel_t;
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
typedef enum {ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */ADC1_CHANNEL_8, /*!< ADC1 channel 6 is GPIO9 */ADC1_CHANNEL_9, /*!< ADC1 channel 7 is GPIO10 */ADC1_CHANNEL_MAX,
} adc1_channel_t;
#elif CONFIG_IDF_TARGET_ESP32C3
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
typedef enum {ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ADC1_CHANNEL_MAX,
} adc1_channel_t;
#endif // CONFIG_IDF_TARGET_*
此为ESP32、ESP32-S2、ESP32-C3的ADC1通道对应的GPIO,不支持重映射。
ADC2的也可在adc_common.h当中查看此处不再罗列。
/*** @brief ADC attenuation parameter. Different parameters determine the range of the ADC. See ``adc1_config_channel_atten``.*/
typedef enum {ADC_ATTEN_DB_0 = 0, /*!<No input attenumation, ADC can measure up to approx. 800 mV. */ADC_ATTEN_DB_2_5 = 1, /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to approx. 1100 mV. */ADC_ATTEN_DB_6 = 2, /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to approx. 1350 mV. */ADC_ATTEN_DB_11 = 3, /*!<The input voltage of ADC will be attenuated, extending the range of measurement to up to approx. 2600 mV. */ADC_ATTEN_MAX,
} adc_atten_t;
这个枚举罗列出了ADC外设所提供的4种衰减增益,确定了4种电压等级,我们也可以在乐鑫的文档中查看到推荐的电压测量范围:
二、进行void ADC_Init(void)函数的编写
1.引入头文件
#include "driver/adc.h"
#include "esp_adc_cal.h"
2.编写初始化函数
#define ADC_TEST_CHANNEL ADC1_CHANNEL_0void ADC_Init(void)
{adc1_config_width(ADC_WIDTH_BIT_13);adc1_config_channel_atten(ADC_TEST_CHANNEL, ADC_ATTEN_11db);
}
ADC捕获通道根据你所使用的进行设置
3.使用int adc1_get_raw(adc1_channel_t channel)进行数据读取
可以看到此函数的返回值为整型,我们先定义一个整型变量用于存储数据;以便将数据打印出来;
其次,根据所选择的数据宽度和基准电压进行计算,这里我们所选择的为13位的数据宽度,所以最大值为 2 13 2^{13} 213,也就是(8192-1),电压衰减增益这里我们设置的为11db,那么对应的基准电压就是2600mV;
我们通过代码将其实现:
int read_raw;ADC_Init();while (1){read_raw = adc1_get_raw(ADC_TEST_CHANNEL);printf("ADC_Raw = %dmV\n", (read_raw * 2600 / 8191));vTaskDelay(1000 / portTICK_PERIOD_MS);}
编译烧录后我们打开串口终端;
通过旋转电位器旋钮来更改电阻值以更改电阻两端的电压;
然后我们查看串口终端打印的数据如下:
为了验证数据的准确性,我们使用万用表测量电位器两端的电压:
万用表测量到的电压与串口终端打印ADC捕获电压相差无几,在可接受的误差范围内,本次实验成功。
更多推荐
[ESP32]学习笔记04
发布评论