ADC
在電子和通信技術中,ADC(模擬數字轉換器)是一種將模擬信號轉換為數字信號的電子設備。這種轉換是電子系統中非常關鍵的一個環節,因為數字信號更易于處理、存儲和傳輸。ADC的工作原理通常包括采樣、保持、量化和編碼等步驟。采樣是從模擬信號中提取離散的值,保持是確保在采樣期間信號值不變,量化是將采樣值轉換為最接近的數字值,而編碼則是將這些數字值表示為二進制代碼。ADC的性能指標包括分辨率、轉換速率和精度等。
ADC在多個領域都有廣泛的應用。在通信領域,ADC用于將模擬信號(如語音信號)轉換為數字信號,以便在無線通信、有線通信和光纖通信系統中進行傳輸。在醫療領域,ADC用于將生物信號(如心電圖和腦電圖)轉換為數字信號,以便于進行醫學分析和診斷。此外,在汽車領域,ADC用于檢測傳感器信號,如發動機轉速、車速和油位等,以實現對汽車系統的精確控制。
?以上介紹來自文心一言。
GD32E230C8T6中的ADC
GD32E230C8T6只有一個ADC,但是可以用的外部通道有10個,還是夠用的。
那么我們需要看看ADC的不同通道對應著哪些GPIO。
可用的GPIO是GPIOA的0號引腳到7號引腳,以及GPIOB的0和1號引腳。
接下來我們來看看怎么使用ADC。
固件庫函數
在介紹ADC相關固件庫之前我們需要先打開外設時鐘。?
rcu_periph_clock_enable(RCU_ADC);
還需要指定一下ADC的時鐘。
rcu_adc_clock_config
可以選擇的選項在上面表格中。關于如何選擇,我們還需要看看GD32E230的時鐘樹。
由于ADC最大只能28MHz,因此配置的時鐘頻率不能大于28MHz。
ADC相關的固件庫函數很多,我這邊就挑著講。
adc_enable
無需參數,調用即可使能ADC外設。
當然了,這個函數我們需要等ADC配置完再調用,可以參考STM32的ADC。這邊先講是因為我按照固件庫使用指南的順序說的,函數具體調用的時機可以參考我最后的示例代碼。
adc_disable
有使能就有失能。調用之后就相當于關閉了ADC外設。
adc_calibration_enable
開啟ADC校準復位。也就是讓ADC開始校準,在STM32中也有類似的做法,不過在GD32的固件庫中我們只需要調用這個函數即可。
adc_channel_length_config
配置通道組的長度,一般來說都是用的規則組(ADC_REGULAR_CHANNEL),我們一共用到幾個ADC通道,我們第二個參數就填幾。
adc_regular_channel_config
設置規則組,設置rank也就是通道序列,還有ADC的通道,一般來說通道幾我們的rank也就是幾。還有就是采樣時間,可供選擇的參數可以參考上表,采樣周期越長,采樣結果越精確,按照實際需求配置就行。
adc_external_trigger_config
配置ADC外部觸發。我們選擇規則組和使能。
這個函數描述會有點歧義,我們ADC一般是由軟件觸發的,實際上軟件觸發也屬于外部觸發的一種,這邊外部觸發的外部和外部中斷的外部不太一樣。
adc_external_trigger_source_config
選擇外部觸發源,我們選擇軟件觸發。?
adc_software_trigger_enable
開啟軟件轉換。
adc_regular_data_read
讀取規則組的ADC的轉換值,但是我們需要在ADC轉換之后再讀取。
adc_flag_get
獲取ADC的標志位,我們在讀取數據之前需要等待ADC轉換結束,用的就是這個函數。
adc_resolution_config
配置ADC分辨率,可以選6,8,10,12位,一般來說我們就多多益善,選擇12位的分辨率。
adc_special_function_config
開啟ADC特殊功能,我們這邊打開掃描模式。如果有用到DMA的話可以選擇連續模式。
adc_data_alignment_config
選擇數據對齊方式,因為存放ADC轉換結果的寄存器是16位,而我們的分辨率是小于16位的,因此我們需要選擇把這12位的數據靠左放還是靠右放,一般就是右對齊。
示例代碼
我們再梳理一下,首先先調用配置函數,配置函數的順序無所謂,都可以。
然后是使能ADC,接著是校準。
最后是讀取數據,開啟軟件觸發之后我們就等待轉換完畢,轉換結束之后調用函數讀取即可。
#include "gd32e23x.h"
#include "systick.h"
#include <stdio.h>
#include "OLED.h"uint16_t getValue(uint8_t ADC_CHANNEL_x){adc_regular_channel_config(0, ADC_CHANNEL_x, ADC_SAMPLETIME_239POINT5); //設置采集通道adc_software_trigger_enable(ADC_REGULAR_CHANNEL); //開始軟件轉換while ( adc_flag_get(ADC_FLAG_EOC) == RESET ) ; //等待 ADC 采樣完成 uint16_t res = adc_regular_data_read(); //讀取采樣值return res;
}int main(void){systick_config(); //延時函數初始化OLED_Init(); //OLED初始化rcu_periph_clock_enable(RCU_GPIOA); //開啟GPIOA的外設時鐘rcu_periph_clock_enable(RCU_ADC); //開啟ADC的外設時鐘rcu_adc_clock_config(RCU_ADCCK_APB2_DIV4); //指定ADC的時鐘為5分頻的APB2(72MHz/4)gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0); //將ADC的對應通道的對應引腳設為模擬輸入adc_special_function_config(ADC_SCAN_MODE, ENABLE); //開啟掃描模式adc_external_trigger_config(ADC_REGULAR_CHANNEL,ENABLE); //開啟規則組外部觸發adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE); //配置規則組為軟件觸發adc_regular_channel_config(0, ADC_CHANNEL_0, ADC_SAMPLETIME_239POINT5); //設置規則組通道adc_data_alignment_config(ADC_DATAALIGN_RIGHT); //數據右對齊adc_resolution_config(ADC_RESOLUTION_12B); //配置分辨率為12位adc_channel_length_config(ADC_REGULAR_CHANNEL, 1); //配置規則組長度為1adc_enable(); //使能ADC adc_calibration_enable(); //開啟校準uint16_t val;OLED_ShowString(1,1,"Hello World");while(1){val=getValue(ADC_CHANNEL_0);OLED_ShowNum(2,1,val,6);delay_ms(1000);}
}