文章目录
- 前言
- 一、ADC
- 二、使用步骤
- 1.DMA程序步骤
- 2.单次采集ADC步骤
- 3.代码分析
- 3.1 DMA读取步骤
- 3.2 单次ADC读取步骤
- 总结
前言
最近入手了一块合宙ESP32C3开发板,只需9.9元自带ble蓝牙和WIFI;从来也没写过博客,以此篇纪念我的第一篇博客,以后的各种小项目以及学习进度都会在这里同步更新。内容上如果有错误的地方,还请各位指教!
这是某个大神写的基础文档,各位可以去了解了解。
一、ADC
以下借鉴内容全部来自官方文档。
https://docs.espressif.com/projects/esp-idf/zh_CN/v4.3.1/esp32c3/api-reference/peripherals/adc.html ADC的全称为Analog to Digital Converter,即模拟到数字的转换,专业术语为模数转换,一般应用于温湿度采集,光照采集等场景。
ESP32C3结合了12位的逐次逼近寄存器ADC,支持总共6个测量通道。分别ADC1的五个引脚GPIO0-GPIO4,ADC2的GPIO5引脚。
注意:
- 由于ADC2模块也被Wi-Fi使用,所以在esp_wifi_start()和esp_wifi_stop()之间adc2_get_raw()的读取操作可能会失败。 使用返回代码查看读取是否成功。
- 一个特定的ADC模块在任何时候只能在一种工作模式下工作,即连续读模式或单读模式。
- ADC1和ADC2不能同时在单读模式下工作。 其中一个会被挡住,直到另一个结束。
- 对于连续(DMA)读取模式,ADC采样频率(adc_digi_config_t的sample_freq_hz成员)应该在SOC_ADC_SAMPLE_FREQ_THRES_LOW和SOC_ADC_SAMPLE_FREQ_THRES_HIGH中。
- ADC单次采集适合低频率模式,DMA连续采集适合高频率模式。未连接任何信号的引脚的ADC读数是随机的。
二、使用步骤
1.DMA程序步骤
- 初始化ADC驱动,使用函数adc_digi_initialize().
- 初始化ADC控制,使用函数adc_digi_controller_config().
- 开始ADC连续读取,使用函数adc_digi_start().
- 在开始之后,你可以得到ADC读取的结果通过函数adc_digi_read_bytes(). 在停止ADC adc_digi_stop()之前你可以连续不断的采集到这个模拟量.
- 重新初始化ADC,使用函数adc_digi_deinitialize().
2.单次采集ADC步骤
ADC在使用前应该被配置好。
- 对于ADC1,通过调用函数adc1_config_width()和adc1_config_channel_atten()来配置所需的精度和衰减。
- 对于ADC2,通过adc2_config_channel_atten()配置衰减。 ADC2的读取宽度在每次读取时配置。
- 然后就可以读取到ADC结果通过adc1_get_raw() and adc2_get_raw()这两个函数。
Attenuation(这个单词查是衰减的意思,但是我感觉不太对)配置应该每个通道都得配,见这两个adc1_channel_t and adc2_channel_t结构体。
这里ESP_IDF的框架基本使用宏定义对GPIO的引脚。
宏ADC1_CHANNEL_0_GPIO_NUM为ADC1通道0的GPIO号。
其中ADC1_GPIOn_CHANNEL为GPIOn的ADC1通道号。 (这里不太理解啥区别)
ADC1_GPIO1_CHANNEL
ADC1_CHANNEL_0_GPIO_NUM
ADC1_GPIO2_CHANNEL
ADC1_CHANNEL_1_GPIO_NUM
ADC1_GPIO3_CHANNEL
ADC1_CHANNEL_2_GPIO_NUM
ADC1_GPIO4_CHANNEL
ADC1_CHANNEL_3_GPIO_NUM
ADC1_GPIO5_CHANNEL
ADC1_CHANNEL_4_GPIO_NUM
ADC2_GPIO5_CHANNEL
ADC2_CHANNEL_0_GPIO_NUM
3.代码分析
3.1 DMA读取步骤
void continuous_read(void *arg)
{
esp_err_t ret;
uint32_t ret_num = 0;
uint8_t result[TIMES] = {0};
memset(result, 0xcc, TIMES);
continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));
adc_digi_start();
while (1)
{
ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY);
for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
adc_digi_output_data_t *p = (void*)&result[i];
printf("Unit: %d,_Channel: %d, Value: %x\n", p->type2.unit+1, p->type2.channel, p->type2.data);
}
vTaskDelay(200);
}
//See `note 1`
adc_digi_stop();
ret = adc_digi_deinitialize();
assert(ret == ESP_OK);
}
分别对应上面DMA采集ADC的1234几个步骤。
3.2 单次ADC读取步骤
所以在官方历程上进行简化就是:
static void single_read(void *arg)
{
// esp_err_t ret;
// int adc1_reading[3] = {0xcc};
int adc1_reading[1] = {0xcc};
// int adc2_reading[1] = {0xcc};
float vout;
// const char TAG_CH[][10] = {"ADC1_CH2", "ADC1_CH3","ADC1_CH4", "ADC2_CH0"};
const char TAG_CH[1][10] = {"ADC1_CH0"};
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);//GPIO0引脚,最大11db
// adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_6);
// adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_0);
// adc2_config_channel_atten(ADC2_CHANNEL_0, ADC_ATTEN_DB_0);
// int n = 20;
// while (n--) {
while (1) {
adc1_reading[0] = adc1_get_raw(ADC1_CHANNEL_0); //ad采集的结果
// adc1_reading[1] = adc1_get_raw(ADC1_CHANNEL_3);
// adc1_reading[2] = adc1_get_raw(ADC1_CHANNEL_4);
vout = (adc1_reading[0] * 2500.00)/4095.00; //
ESP_LOGI(TAG_CH[0], "%x vout mv is %f", adc1_reading[0],vout);
// for (int i = 0; i < 3; i++) {
// ESP_LOGI(TAG_CH[i], "%x", adc1_reading[i]);
// }
// ret = adc2_get_raw(ADC2_CHANNEL_0, ADC_WIDTH_BIT_12, &adc2_reading[0]);
// assert(ret == ESP_OK);
// ESP_LOGI(TAG_CH[3], "%x", adc2_reading[0]);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
总结
本文仅仅简单介绍了ESP32C3_ADC的使用,下一篇再见。