第二十四章 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 例程功能
- 本章實驗功能簡介:使用ADC採集通道7(IO8)上面的電壓,在SPILCD模塊上面顯示ADC轉換值以及換算成電壓後的電壓值。在P3端口中,使用短路帽將AIN和RV1排針連接,使得IO8連接到電位器上,然後將ADC採集到的數據和轉換後的電壓值在SPILCD屏中顯示。用户可以通過調節電位器的旋鈕改變電壓值。LED閃爍,提示程序運行。
- LED閃爍,指示程序正在運行。
24.2.2 硬件資源
- LED
LED - IO1 - XL9555
IIC_SDA-IO41
IIC_SCL-IO42 - SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳線帽將IO_SET和LCD_DC相連)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555) - 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顯示效果圖