博客 / 詳情

返回

《ESP32-S3使用指南—IDF版 V1.6》第二十四章 ADC實驗

第二十四章 ADC實驗

1)實驗平台:正點原子DNESP32S3開發板

2)章節摘自【正點原子】ESP32-S3使用指南—IDF版 V1.6

3)購買鏈接:https://detail.tmall.com/item.htm?&id=768499342659

4)全套實驗源碼+手冊+視頻下載地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html

5)正點原子官方B站:https://space.bilibili.com/394620890

6)正點原子DNESP32S3開發板技術交流羣:132780729

本章介紹使用ESP32-S3模數轉換器(ADC)進行帶通道的電壓採集。通過本章的學習,讀者將學習到單通道ADC的使用。
本章分為如下幾個小節:
24.1 ADC簡介
24.2 硬件設計
24.3 程序設計
24.4 下載驗證

24.1 ADC介紹

24.1.1 ADC簡介

生活中接觸到的大多數信息是醉着時間連續變化的物理量,如聲音、温度、壓力等。表達這些信息的電信號,稱為模擬信號(Analog Signal)。為了方便存儲、處理,在計算機系統中,都是數字0和1信號,將模擬信號(連續信號)轉換為數字信號(離散信號)的器件就叫模數轉換器(Analog-to-Digital Convert,ADC)。
ADC轉換器可分為:並行比較型A/D轉換器(FLASH ADC)、逐次比較型A/D轉換器(SAR ADC)和雙積分式A/D轉換器(Double Integral ADC)。
A/D轉換過程通常為4步:採樣、保持、量化和編碼,如下圖所示。

圖24.1.1.1 A/D轉換過程圖

採樣:把時間連續變化的信號變換為時間離散的信號。
保持:保持採樣信號,使有充分時間轉換為數字信號。
量化:把採樣保持電路的輸出信號用單位量化電壓的整數倍表示。
編碼:把量化的結果用二進制代碼表示。
採樣和保持通常是在採樣-保持電路中完成,量化和編碼通常在ADC數字編碼電路中完成。

24.1.2 ESP32-S3 ADC介紹

ESP32-S3集成了兩個12位SAR ADC,ADC1和ADC2,支持20個模擬通道輸入。這20個模擬通道輸入對應着具體的IO,並不是隨意的IO都有模擬輸入功能,具備模擬輸入功能的引腳如下表所示。

表24.1.2.1 具備模擬輸入功能的引腳
ESP32-S3的ADC模塊的分辨率為12位,所以AD轉換後的值範圍為0~4095。由於ESP32-S3的工作電壓為3.3V,所以當AD值為4095時,對應的電壓為3.3V;當AD值為0時,對應的電壓為0V。對於AD值和電壓值,這裏就會有一個簡單的關係,如下所示。

24.2 硬件設計

24.2.1 例程功能

  1. 本章實驗功能簡介:使用ADC採集通道7(IO8)上面的電壓,在SPILCD模塊上面顯示ADC轉換值以及換算成電壓後的電壓值。在P3端口中,使用短路帽將AIN和RV1排針連接,使得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_SET和LCD_DC相連)
    PWR- IO1_3(XL9555)
    RST- IO1_2(XL9555)
  4. ADC
    ADC1_CHANNEL_7

24.2.3 原理圖

ADC屬於ESP32-S3內部資源,實際上我們只需要軟件設置就可以正常工作,另外還需要將待測量的電壓源連接到ADC通道上,以便ADC測量。本實驗,我們通過ADC1的通道7(IO8)來採集外部電壓值,開發板有一個電位器,可調節的電壓範圍是:0~3.3V。我們可以通過跳線帽將IO8與電位器連接,如下圖所示:

圖24.2.3.1 IO8(對應AIN排針)與電位器引腳示意圖
使用杜邦線將ADC和RV1排針連接好後,並下載程序後,就可以用螺絲刀調節電位器變換多種電壓值進行測量。
有的朋友可能還想測量其它地方的電壓值,我們只需要1根杜邦線,一端接到AIN排針上,另外一端就接你要測試的電壓點。一定要保證測試點的電壓在0~3.3V的電壓範圍,否則可能燒壞我們的ADC,甚至是整個主控芯片。

24.3 程序設計

24.3.1 程序流程圖

程序流程圖能幫助我們更好的理解一個工程的功能和實現的過程,對學習和設計工程有很好的主導作用。下面看看本實驗的程序流程圖:

圖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);

該函數的形參描述,如下表所示:

表24.3.2.1 函數adc_digi_controller_configure()形參描述
返回值:ESP_OK表示配置成功。其他表示配置失敗。
該函數使用adc_digi_pattern_config_t以及adc_digi_configuration_t類型的結構體變量傳入,該結構體的定義如下所示:

表24.3.2.2 adc_digi_pattern_config_t結構體參數值描述

表24.3.2.3 adc_digi_configuration_t結構體參數值描述

完成上述結構體參數配置之後,可以將結構傳遞給 adc_digi_controller_configure() 函數,用以實例化ADC。
2,讀取ADC原始數據
該函數用於讀取ADC原始數據,其函數原型如下所示:

int adc1_get_raw(adc1_channel_tchannel);

該函數的形參描述,如下表所示:

表24.3.2.4 函數adc1_get_raw()形參描述
返回值:其他值表示ADC原始數值,-1表示讀取失敗。

24.3.3 ADC驅動解析

在IDF版14_adc例程中,作者在14_adc \components\BSP路徑下新增了一個ADC文件夾,分別用於存放adc.c、adc.h這兩個文件。其中,adc.h文件負責聲明ADC相關的函數和變量,而adc.c文件則實現了ADC的驅動代碼。下面,我們將詳細解析這兩個文件的實現內容。
1,adc.h文件

/* ADC採集通道定義 */
#define ADC_ADCX_CHY  ADC1_CHANNEL_7

2,adc.c文件

/**
* @brief       初始化ADC
* @param       無
* @retval      無
*/
void adc_init(void)
{
adc_digi_pattern_config_tadc1_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      通道ch的times次轉換結果平均值
*/
uint32_tadc_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通道7(IO8引腳)採集到電壓的數字量和模擬量,此時可以通過杜邦線給IO8引腳接入不同的電壓值(注意共地,且輸入電壓不能超過3.3V,否則可能損壞開發板),可以看到LCD上顯示的電壓數字量和模擬量也隨之改變。

圖24.4.1 SPI LCD顯示效果圖

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.