文章目录

  • 前言
  • 一、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引脚。
注意:

  1. 由于ADC2模块也被Wi-Fi使用,所以在esp_wifi_start()和esp_wifi_stop()之间adc2_get_raw()的读取操作可能会失败。 使用返回代码查看读取是否成功。
  2. 一个特定的ADC模块在任何时候只能在一种工作模式下工作,即连续读模式或单读模式。
  3. ADC1和ADC2不能同时在单读模式下工作。 其中一个会被挡住,直到另一个结束。
  4. 对于连续(DMA)读取模式,ADC采样频率(adc_digi_config_t的sample_freq_hz成员)应该在SOC_ADC_SAMPLE_FREQ_THRES_LOW和SOC_ADC_SAMPLE_FREQ_THRES_HIGH中。
  5. ADC单次采集适合低频率模式,DMA连续采集适合高频率模式。未连接任何信号的引脚的ADC读数是随机的。

二、使用步骤

1.DMA程序步骤

  1. 初始化ADC驱动,使用函数adc_digi_initialize().
  2. 初始化ADC控制,使用函数adc_digi_controller_config().
  3. 开始ADC连续读取,使用函数adc_digi_start().
  4. 在开始之后,你可以得到ADC读取的结果通过函数adc_digi_read_bytes(). 在停止ADC adc_digi_stop()之前你可以连续不断的采集到这个模拟量.
  5. 重新初始化ADC,使用函数adc_digi_deinitialize().

2.单次采集ADC步骤

ADC在使用前应该被配置好。

  1. 对于ADC1,通过调用函数adc1_config_width()和adc1_config_channel_atten()来配置所需的精度和衰减。
  2. 对于ADC2,通过adc2_config_channel_atten()配置衰减。 ADC2的读取宽度在每次读取时配置。
  3. 然后就可以读取到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读取步骤

esp32adc转化模拟输入电路图 esp32 adc引脚_引脚


esp32adc转化模拟输入电路图 esp32 adc引脚_物联网_02

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读取步骤

esp32adc转化模拟输入电路图 esp32 adc引脚_esp32adc转化模拟输入电路图_03


所以在官方历程上进行简化就是:

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的使用,下一篇再见。