ADC
我们照例是请文心一言来介绍一下ADC。
ADC具有多重含义,以下为你详细介绍其中两种主要的含义:
首先,ADC在电子游戏领域中,特别是在MOBA类游戏中,指的是Attack Damage Carry或Attack Damage Core,即普通攻击持续输出核心。它代表那些以普通攻击为主要输出方式,能造成持续伤害输出的角色。在《刀塔》这样的游戏中,ADC通常指的是那些以物理攻击为主要输出方式的核心英雄。而在《英雄联盟》中,ADC英雄则经常被用于“下路”位置,尽管随着游戏的发展,非ADC英雄走下路的现象逐渐增多,但在赛事场合中,ADC仍然是对这一位置的重要称呼。
其次,ADC也是Analog-to-Digital Converter的缩写,即模拟数字转换器。这是一种将连续变量的模拟信号转换为离散的数字信号的器件。ADC在多个领域都有广泛的应用,包括通信、医疗、汽车、测量和控制等。例如,在无线通信系统中,ADC用于将模拟语音信号转换为数字信号进行传输;在医疗设备中,ADC用于将生物信号如心电图和脑电图转换为数字信号,以便进行分析和存储;在汽车领域,ADC用于检测传感器信号,如发动机转速和车速,从而控制发动机和车辆的其他系统。
AI的回答咱随便看看就行。
ADC就是把模拟信号转换为数字信号用的。
关于ESP32中的ADC,官方文档的介绍很简短,几乎没有,也可能是我没找对地方。
在两个文档中各自都只有一句简短的概括。
但是我们也可以从中提取一点信息出来。
首先ESP32中是有两个ADC。
第二,ADC的分辨率是12位。
接下来看看编程指南中如何使用ADC。
使用ADC
#include "hal/adc_types.h"
编程指南中列了好多条,但实际上我们只需要配置前三个即可。
首先是资源分配。
接着就出现问题了,在IDE中没有相关的函数提示。
可能是我安装的IDF版本和编程指南里的不一样,因此我没有相关函数。
这条路走不通,还有别的办法,可以参考立创开发板提供的文档。
#include "esp_adc_cal.h"
#include "driver/adc.h"
接下来进行两个配置。
第一个是配置adc1的精度,esp32中一共有俩adc,分别是adc1和adc2,按理说我们都可以用。但是我们最好就是用adc1,每个adc有十个通道,所以一个也是够用的。
至于为什么不用adc2,这是因为adc2和WiFi是冲突的,而WiFi基本上是咱物联网的标配,因此为了避免冲突,咱就是用adc1。
void adc1_config_width(adc_bits_width_t width);
可选的参数有9~13位精度的,但是根据之前的文档我们知道,ESP32中的ADC只有最高12位精度,因此13那个选项不能选(应该吧)。
下一个是衰减参数,衰减越大,可接受的电压越大。
void adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
第一个参数选择通道,我们知道每个ADC都有十个通道,因此可选的有十个。
第二个选择衰减参数。
这个根据自己手上的传感器的电气参数来选择,不清楚的话就先选11db的,这样就算电压范围不一样也不会导致板子烧坏。
接下来就可以读取ADC的值了。
int adc1_get_raw(adc1_channel_t channel);
另外需要说的是ADC的通道对应的GPIO口是固定的。
从上面的表格看出我们能用的ADC1的通道只有8个而不是10个。
然而还有个问题就是adc1的不同通道对应的GPIO口。
在实测之后我发现adc1的通道0对应的是GPIO1,但是我找了很多地方说的都是像上面表格一样。
然后我找到了立创开发板的图。
因此大家优先以自己买的板子提供的引脚对应表为准。
如果没有的话再按照上面编程指南中提供的表格。
完整实操代码
#include <stdio.h>
#include "driver/gpio.h"
#include "driver/adc.h"
#include <unistd.h>
void app_main(void){
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_DB_11);
while (1){
uint16_t adc_val = adc1_get_raw(ADC1_CHANNEL_0);
printf("%d\r\n",adc_val);
sleep(1);
}
}
我在GPIO1的位置接了个光敏电阻,能够正常转换。
像上面那样使用adc还是很简单的,我看立创开发板还提供了另一种加上了校准的写法,我贴在下面。
#include <string.h>
#include <stdio.h>
#include "sdkconfig.h"
#include <esp_log.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#define DEFAULT_VREF 1100 //默认参考电压,单位mV
static esp_adc_cal_characteristics_t *adc_chars;
#define channel ADC_CHANNEL_0 // ADC测量通道
#define width ADC_WIDTH_BIT_12 // ADC分辨率
#define atten ADC_ATTEN_DB_11 // ADC衰减
#define unit ADC_UNIT_1 // ADC1
void app_main(void)
{
int read_raw_1=0, read_raw_2=0, read_raw_3=0;
uint32_t voltage =0;
float voltage_f = 0;
adc1_config_width(width);// 12位分辨率
//ADC_ATTEN_DB_0:表示参考电压为1.1V
//ADC_ATTEN_DB_2_5:表示参考电压为1.5V
//ADC_ATTEN_DB_6:表示参考电压为2.2V
//ADC_ATTEN_DB_11:表示参考电压为3.3V
//adc1_config_channel_atten( channel,atten);// 设置通道0和3.3V参考电压
// 分配内存
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
// 对 ADC 特性进行初始化,使其能够正确地计算转换结果和补偿因素
esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
while(1)
{
//采集三个通道的ADC值
read_raw_1 = adc1_get_raw(ADC1_CHANNEL_0); //GPIO1
read_raw_2 = adc1_get_raw(ADC1_CHANNEL_1); //gpio2
read_raw_3 = adc1_get_raw(ADC1_CHANNEL_2); //gpio3
//将ADC1的通道0(gpio1)的结果转换成电压,单位mV
voltage = esp_adc_cal_raw_to_voltage(read_raw_1, adc_chars);
//输出ADC值 与 ADC1通道0(GPIO1)实际电压值
printf("read_raw_1 = %d\tread_raw_2 = %d\tread_raw_3 = %d\tvoltage: %f\n",read_raw_1,read_raw_2,read_raw_3,voltage/1000.0);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}