11.1實驗內容
通過本實驗主要學習以下內容:
11.2實驗原理
11.2.1ADC原理
我們知道,自然界中有非常多的模擬信號,比如上一節(jié)提到的光照強度,還有其他的例如溫度、聲音等等,那么人們是怎么來衡量一個模擬信號的呢?
我們通常會說今天光照度達到了3萬Lux(照度單位),現(xiàn)在測量到的體溫是36.5℃,我們所處的環(huán)境是40分貝,沒錯,人們就是通過將這些模擬信號數(shù)字化,從而達到衡量這些模擬信號的目的。那對于MCU來說,如果要測量一個模擬量,可以通過自帶的ADC(Analog-to-Digital converters)模塊,即模-數(shù)轉換器將模擬量轉化為可以被MCU讀取到的數(shù)字量。
11.2.2GD32F303 ADC工作原理
GD32F303有3個12位逐次逼近型ADC(SAR ADC),這三個ADC可以獨立工作,也可以讓ADC0和ADC1工作在同步模式下。有最多21個外部ADC引腳可用于將連接到這些引腳的電壓值轉換為數(shù)字量,這些引腳號可以通過Datasheet獲得。

表中ADC012_INx的意思是:該IO口可以作為通道x用于ADC0、ADC1和ADC2。如ADC012_IN0,表示PA0可以用于ADC0的通道0使用,也可以作為ADC1和ADC2的通道0使用。但要注意:不能在同一個時刻讓不同的ADC去轉換同一個通道,否則會有無法預料的結果 |
以下總結了GD32F303 ADC的特性:
- 高性能:
–可配置12位、10位、8位、或者6位分辨率;
–自校準;
–可編程采樣時間;
–數(shù)據(jù)寄存器可配置數(shù)據(jù)對齊方式;
–支持規(guī)則數(shù)據(jù)轉換的DMA請求。 - 模擬輸入通道:
– 16個外部模擬輸入通道;
– 1個內部溫度傳感器輸入通道(VSENSE);
– 1個內部參考電壓輸入通道(VREFINT)。 - 轉換開始的發(fā)起:
–軟件;
–硬件觸發(fā)。 - 轉換模式:
–轉換單個通道,或者掃描一組通道;
–單次模式,每次觸發(fā)轉換一次選擇的輸入通道;
–連續(xù)模式,連續(xù)轉換所選擇的輸入通道;
–間斷模式;
–同步模式(適用于具有兩個或多個ADC的設備)。 - 模擬看門狗。
- 中斷的產生:
–規(guī)則組或注入組轉換結束;
–模擬看門狗事件。 - 過采樣:
– 16位的數(shù)據(jù)寄存器;
–可調整的過采樣率,從2x到256x;
–高達8位的可編程數(shù)據(jù)移位。 - ADC供電要求:
– 2.4V到3.6V,一般供電電壓為3.3V。 - ADC輸入范圍:VREFN ≤VIN ≤VREFP 。
下面介紹下GD32F303的ADC框圖:

標注1:輸入電壓和參考電壓
輸入電壓引腳定義如下表:

大于等于100pin的GD32F303,ADC參考電壓等于VREFP,100pin以下的GD32F303,ADC參考電壓等于VDDA |
GD32F303的ADC是12bit有效位的,滿量程對應的轉換值是4095,即當采樣引腳上的電壓等于ADC參考電壓時,得到的轉換值即為4095。故理論采樣是指可通過以下公式得到:采樣數(shù)值=實際電壓/參考電壓*4095
標注2:輸入通道
前面提到,ADC有最多16個外部模擬通道和2個內部通道,外部通道號從IN0~IN15,由IO口號來決定,兩個內部通道是IN16(溫度傳感器)和IN17(內部Vrefint,典型值1.2V),下表給出了IO口號對應的ADC通道:

標注3:規(guī)則組和注入組
每個ADC有兩個組——規(guī)則組和注入組。
規(guī)則組有兩個重要的參數(shù),其一為轉換的個數(shù),其二為轉換的序列,規(guī)定好這兩個參數(shù)后,一旦開始規(guī)則組的轉換,則ADC就按照轉換序列一個一個的進行模-數(shù)轉換,直到達到要求的轉換個數(shù)。
規(guī)則組的轉換個數(shù)由ADC_RSQ0寄存器的RL[3:0]位規(guī)定,轉換的總數(shù)目為RL[3:0]+1,轉換總數(shù)目最大為16個;轉換序列由ADC_RSQ0~ADC_RSQ2共同決定,我們來看下這幾個寄存器。
ADC_RSQ0寄存器:


ADC_RSQ1寄存器:

ADC_RSQ2寄存器:

舉個例子,現(xiàn)需要按照CH3->CH2->CH1的順序進行規(guī)則組轉換,則設定RL[3:0] = 2,然后設定RSQ0為CH3,RSQ1為CH2,RSQ2為CH1,則當開始規(guī)則組轉換時,ADC首先進行RSQ0規(guī)定的通道即CH3的轉換,再進行RSQ1規(guī)定的通道即CH2的轉換,最后進行RSQ2規(guī)定的通道即CH1轉換,當這三個通道轉換完后,規(guī)則組轉換結束。
需要注意的是,每轉換一個規(guī)則組通道,轉換結果都會放在寄存器ADC_RDATA中,所以CPU一定要在下一個通道轉換完成前將上一個通道轉換結果讀走,否則會導致上一個通道數(shù)據(jù)被新的數(shù)據(jù)覆蓋。所以在多通道規(guī)則組轉換時,為了保證能讀到所有通道的數(shù)據(jù),一定要使用DMA(直接存儲器訪問控制器),每個通道轉換結束后,都會給DMA發(fā)送請求,DMA就會將最新的ADC_RDATA中的數(shù)據(jù)搬走。關于ADC配合DMA的使用,后面章節(jié)會詳細介紹。
說完規(guī)則組,我們再說下注入組。注入組,可以按照特定的序列組織成最多 4 個轉換的序列。ADC_ISQ寄存器規(guī)定了注入組的通道選擇。ADC_ISQ寄存器的IL[1:0]位規(guī)定了整個注入組轉換序列的長度。
ADC_ISQ寄存器:

和規(guī)則組轉換序列不同的是,如果 IL[1:0]長度不足4,注入通道轉換從(4-IL[1:0]-1)開始:
當IL = 3,注入組轉換順序為ISQ0 >> ISQ1 >> ISQ2 >> ISQ3,轉換結果分別放在ADC_IDATA0~ADC_IDATA3;
當IL = 2,注入組轉換順序為ISQ1 >> ISQ2 >> ISQ3,轉換結果分別放在ADC_IDATA0~ADC_IDATA2;
當IL = 1,注入組轉換順序為ISQ2 >> ISQ3,轉換結果分別放在ADC_IDATA0~ADC_IDATA1;
當IL = 0,注入組轉換ISQ3,轉換結果放在ADC_IDATA0
舉個例子,現(xiàn)需要按照CH3->CH2->CH1的順序進行注入組轉換,則設定IL[3:0] = 2,然后設定ISQ1為CH3,ISQ2為CH2,ISQ3為CH1,則當開始注入組轉換時,ADC首先進行ISQ1規(guī)定的通道即CH3的轉換,再進行ISQ2規(guī)定的通道即CH2的轉換,最后進行ISQ3規(guī)定的通道即CH1轉換,當這三個通道轉換完后,注入組轉換結束。
因為4個通道轉換的結果分別放在4個不同的注入組數(shù)據(jù)寄存器ADC_IDATAx中,所以注入組不需要用到DMA,只需要在注入組轉換完成后分別去不同注入組數(shù)據(jù)寄存器中取數(shù)即可。
標注4:觸發(fā)源
ADC的規(guī)則組和注入組需要選特定的觸發(fā)源用于觸發(fā)ADC轉換,注意,ADC的Enable(即ADC_CTL1寄存器的ADC_ON位置“1”)不會觸發(fā)ADC轉換,而是當選定的觸發(fā)源來臨后ADC才開始轉換。
觸發(fā)源分為內部觸發(fā)和外部觸發(fā),內部觸發(fā)是指當ADC_ON已經為“1”的情況下,不改變其他ADC寄存器,再往ADC_ON位寫“1”,將觸發(fā)一次ADC轉換;外部觸發(fā)源是除了內部觸發(fā)源以外的觸發(fā)源,外部觸發(fā)源可以通過ADC_CTL1寄存器查看:
ADC_CTL1寄存器:





標注5:規(guī)則組和注入組的數(shù)據(jù)寄存器
如標注3規(guī)則組和注入組中的表述,每個ADC的規(guī)則組只有一個數(shù)據(jù)寄存器ADC_RDATA,每轉換一個通道,轉換結果放在這個寄存器中,在下一通道轉換結束前必須要將上一個通道的轉換結果取走;每個ADC的注入組有4個數(shù)據(jù)寄存器ADC_IDATAx(x = 0,1,2,3),分別保存4個通道的ADC注入組的轉換數(shù)據(jù)。
標注6:ADC中斷及標志位
ADC的中斷總共有三種:規(guī)則組轉換結束中斷、注入組轉換結束中斷以及模擬看門狗,可以通過將ADC_CTL0中的EOCIE、EOICIE和WDEIE置“1”來開啟相應中斷。
ADC_STAT寄存器中的EOC、EOIC和WDE表示相應事件發(fā)生,EOC置“1”表示規(guī)則組的轉換已經結束;EOIC置“1”表示注入組的轉換已經結束,注意:注入組轉換結束時,EOC標志位也會置起。
GD32F303的ADC原理部分就介紹到這里,下面我們通過電源電壓單通道采樣實驗來詳細介紹下ADC的用法。
11.3硬件設計
電源電壓檢測的原理圖如下:

ADC_IN4連接到MCU的PF6管腳通過ADC轉換可以得到PF6腳上具體的電壓值,再通過該電壓值可反推電源電壓值。
11.4代碼解析
本實驗只用到一個ADC通道:PF6——ADC2_CH4,故可以選擇使用ADC2的規(guī)則組進行轉換,并通過查詢EOC標志位來判斷通道轉換完成。
11.4.1ADC初始化
在driver_adc.c中定義了ADC初始化函數(shù)driver_adc_config:
C void driver_adc_config(typdef_adc_ch_general *ADC,typdef_adc_ch_parameter *ADC_CH) { uint8_t i; /*配置ADC時鐘頻率*/ rcu_adc_clock_config(ADC->adc_psc); /*使能ADC時鐘*/ rcu_periph_clock_enable(ADC->rcu_adc); /*配置ADC相關IO口,先配置時鐘,再將IO口設置為模擬輸入*/ for(i=0 ;ich_count; i++) { if(ADC_CH[i].adc_channel < ADC_CHANNEL_16) { rcu_periph_clock_enable(ADC_CH[i].rcu_port); gpio_init(ADC_CH[i].port, GPIO_MODE_AIN, ADC_CH[i].gpio_speed, ADC_CH[i].pin); } else { adc_tempsensor_vrefint_enable(); } } /*配置ADC工作模式,如獨立模式,規(guī)則并行模式等*/ adc_mode_config(ADC->adc_mode); /*配置規(guī)則組的掃描模式和連續(xù)轉換模式*/ adc_special_function_config(ADC->adc_port, ADC_SCAN_MODE, ADC->adc_scan_function); if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL) { adc_special_function_config(ADC->adc_port, ADC_CONTINUOUS_MODE, ADC->adc_continuous_function); } /*選擇數(shù)據(jù)右對齊*/ adc_data_alignment_config(ADC->adc_port, ADC_DATAALIGN_RIGHT); /*配置轉換通道數(shù)*/ adc_channel_length_config(ADC->adc_port, ADC->adc_channel_group, ADC->ch_count); /*配置轉換順序*/ if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL) { for(i = 0;i< ADC->ch_count;i++) { adc_regular_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time); } } else if(ADC->adc_channel_group == ADC_INSERTED_CHANNEL) { for(i = 0;i< ADC->ch_count;i++) { adc_inserted_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time); } } /*選擇觸發(fā)源及使能外部觸發(fā)模式*/ adc_external_trigger_source_config(ADC->adc_port, ADC->adc_channel_group, ADC->trigger_source); adc_external_trigger_config(ADC->adc_port, ADC->adc_channel_group, ENABLE); /*選擇是否需要使用DMA*/ if(ADC->DMA_mode == ENABLE) { adc_dma_mode_enable(ADC->adc_port); } /*ADC的使能和自校準,ADC使能后需要經過一定的ADC_CLK后才能校準,本示例中直接使用1ms延時*/ adc_enable(ADC->adc_port); delay_ms(1); adc_calibration_enable(ADC->adc_port); } |
在解析上述代碼前,我們先看driver_adc.h兩個結構體聲明。
1、ADC設置參數(shù)結構體,該結構體中規(guī)定了ADC設置所需要的參數(shù):
C /*ADC設置參數(shù)*/ typedef struct __typdef_adc_general { rcu_periph_enum rcu_adc;//ADC時鐘口 uint32_t adc_psc;//ADC時鐘源分頻系數(shù) uint32_t adc_port;//ADC號 uint32_t adc_mode;//ADC工作模式:ADC_MODE_FREE,ADC_DAUL_REGULAL_PARALLEL uint8_t adc_channel_group;//ADC工作組:規(guī)則組或注入組 EventStatus adc_scan_function;//設置掃描模式 EventStatus adc_continuous_function;//設置循環(huán)模式 uint8_t ch_count;//設置轉換通道個數(shù) typdef_adc_dma_parameter dma_parameter;//若使用DMA,則需要設置dma uint32_t trigger_source;//ADC觸發(fā)源 EventStatus DMA_mode;//是否使用DMA }typdef_adc_ch_general; |
2、ADC IO口及通道參數(shù)結構體,該結構體中規(guī)定了用于ADC轉換的IO口及通道參數(shù):
C /*ADC IO口及通道參數(shù)*/ typedef struct __typdef_adc_ch_parameter { rcu_periph_enum rcu_port;//IO口時鐘 uint32_t port;//IO port uint32_t pin;//IO pin uint32_t gpio_speed;//IO 速率 uint8_t adc_channel;//IO對應的ADC通道 uint32_t sample_time;//IO的采樣周期 }typdef_adc_ch_parameter; |
好,現(xiàn)在我們來對ADC配置進行分段解析。
1、ADC的時鐘頻率配置和ADC時鐘使能:
C /*配置ADC時鐘頻率*/ rcu_adc_clock_config(ADC->adc_psc); /*使能ADC時鐘*/ rcu_periph_clock_enable(ADC->rcu_adc); |
GD32F303的ADC的工作時鐘頻率不能超過40MHz,而ADC是掛載在APB2總線上的,APB2總線最高頻率可以達到120M,所以需要進行分頻處理。
2、配置IO口
C /*配置ADC相關IO口,先使能時鐘,再將IO口設置為模擬輸入*/ for(i=0 ;ich_count; i++) { if(ADC_CH[i].adc_channel < ADC_CHANNEL_16) { rcu_periph_clock_enable(ADC_CH[i].rcu_port); gpio_init(ADC_CH[i].port, GPIO_MODE_AIN, ADC_CH[i].gpio_speed, ADC_CH[i].pin); } else { adc_tempsensor_vrefint_enable(); } } |
被用作ADC采樣的IO口需要被設置為Analog模式,因為ADC_CH0~ADC_CH15是和外部IO關聯(lián)的,而ADC_CH16和ADC_CH17是內部通道,所以只有在通道號小于ADC_CHANNEL_16時才需要配置IO口,而大于等于ADC_CHANNEL_16時需要使能ADC內部通道。
3、配置ADC規(guī)則組工作模式
C /*配置ADC工作模式,如獨立模式,規(guī)則并行模式等*/ adc_mode_config(ADC->adc_mode); |
ADC的模式有獨立模式、規(guī)則并行、注入并行、快速交叉等9種,其中用到比較多的是獨立模式、規(guī)則并行和注入并行,現(xiàn)對這三種做簡單介紹。
獨立模式:三個ADC相互之間無影響,每個ADC單獨工作;
規(guī)則并行:ADC0和ADC1可工作規(guī)則并行模式下,當ADC0規(guī)則組被觸發(fā)開始轉換時,ADC1注入組也會自動開始轉換(此時ADC1的觸發(fā)源一定要選擇軟件觸發(fā)),轉換結果會分別放在ADC0_RDATA和ADC1_RDATA中,其中ADC0_RDATA的上半字也會保存ADC1的轉換結果,這樣設計是為了方便DMA去進行兩個同步ADC結果的同時搬運。
基于16個通道的規(guī)則并行模式如下圖所示:

注意: |
注入并行:ADC0和ADC1可工作注入并行模式下,當ADC0注入組被觸發(fā)開始轉換時,ADC1注入組也會自動開始轉換(此時ADC1的觸發(fā)源一定要選擇軟件觸發(fā)),和規(guī)則組不同的是,通道轉換結果會放在各自的ADC_IDATAx寄存器中 。
基于4個通道的注入并行模式如下圖所示:

4、配置掃描和連續(xù)模式
C /*配置規(guī)則組的掃描模式和連續(xù)轉換模式*/ adc_special_function_config(ADC->adc_port, ADC_SCAN_MODE, ADC->adc_scan_function); if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL) { adc_special_function_config(ADC->adc_port, ADC_CONTINUOUS_MODE, ADC->adc_continuous_function); } |
掃描模式:當一個規(guī)則組或注入組規(guī)定了1個以上的通道轉換時,需要開啟掃描模式,此時規(guī)則組或注入組會根據(jù)設定好的轉換順序對通道一個一個進行轉換;如果關閉掃描模式,那么規(guī)則組和注入組只會轉換RSQ0和ISQ0規(guī)定的通道。
連續(xù)模式:該模式只適用于規(guī)則組,開啟該模式時,當規(guī)則組轉換完成后,會自動開始新一輪的轉換。
下圖為掃描轉換模式,且連續(xù)轉換模式失能的轉換情況:

下圖為掃描轉換模式,連續(xù)轉換模式使能的轉換情況:

5、設置數(shù)據(jù)對齊
C /*選擇數(shù)據(jù)右對齊*/ adc_data_alignment_config(ADC->adc_port, ADC_DATAALIGN_RIGHT); |
ADC的轉換結果可以選擇左對齊或右對齊,以12位結果為例,左右對齊如下:

6、配置轉換個數(shù)、轉換順序及通道采樣周期
C /*配置轉換通道數(shù)*/ adc_channel_length_config(ADC->adc_port, ADC->adc_channel_group, ADC->ch_count); /*配置轉換順序*/ if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL) { for(i = 0;i< ADC->ch_count;i++) { adc_regular_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time); } } else if(ADC->adc_channel_group == ADC_INSERTED_CHANNEL) { for(i = 0;i< ADC->ch_count;i++) { adc_inserted_channel_config(ADC->adc_port, i, ADC_CH[i].adc_channel,ADC_CH[i].sample_time); } } |
這段程序是配置規(guī)則組和注入組的轉換長度、轉換順序及通道采樣周期。轉換長度和順序前面講過,不再贅述,這里簡單介紹下采樣周期。
采樣周期通過adc_regular_channel_config和adc_inserted_channel_config函數(shù)的最后一個形參設置,相應的寄存器是ADC_SAMPT0和ADC_SAMPT1。


GD32F303是SAR ADC(逐次逼近型ADC),內部有采樣電容,采樣過程為先將內部采樣電容和外部采樣引腳相連,通過對內部采樣電容的充放電讓采樣電容和外部采樣引腳電壓相等,然后關閉內外部電路通道,內部再通過逐次逼近比較得到電壓的數(shù)字值。逐次比較的過程需要固定的1.5個采樣周期,而采樣電容充放電過程是可以設置的,即這里介紹的采樣周期。
采樣周期分8個檔位可選,如一個通道選擇12.5周期,則轉換過程需要的總周期數(shù)為12.5+1.5 = 14,如果設置ADC的時鐘(前面提到,ADC時鐘是通過APB2總線經過分頻所得)為30M,那么該通道轉換所需要的時間為14/30M = 0.467us。
那么如何選擇合適的采樣周期,這個和內部采樣電容的充放電時間有關,如果充放電時間不夠,采樣電容電壓不能和外部采樣引腳電壓一致,則得不到準確的采樣值,如充放電時間過長,則浪費CPU資源。我們可以根據(jù)采樣引腳對內輸入阻抗值大小來選擇合適的采樣周期,阻抗值和采樣周期對應表可以通過GD32F303 Datasheet ADC電氣參數(shù)章節(jié)獲得:

舉個例子,實際采樣引腳對內阻抗為20kΩ,根據(jù)上表需要選擇的采樣周期為55.5。
7、選擇ADC規(guī)則組和注入組的觸發(fā)源以及使能外部觸發(fā)
C /*選擇觸發(fā)源及使能外部觸發(fā)模式*/ adc_external_trigger_source_config(ADC->adc_port, ADC->adc_channel_group, ADC->trigger_source); adc_external_trigger_config(ADC->adc_port, ADC->adc_channel_group, ENABLE); |
8、選擇是否需要DMA
C /*選擇是否需要使用DMA*/ if(ADC->DMA_mode == ENABLE) { adc_dma_mode_enable(ADC->adc_port); } |
只有規(guī)則組才能使用DMA,在規(guī)則組設置了多通道采樣即掃描模式打開時,是一定要用DMA的,否則沒辦法及時將轉換完成的通道數(shù)據(jù)取走,其他的情況下DMA是否使用根據(jù)實際應用決定。
9、ADC的使能和自校準
C /*ADC的使能和自校準,ADC使能后需要經過一定的ADC_CLK后才能校準,本示例中直接使用1ms延時*/ adc_enable(ADC->adc_port); delay_ms(1); adc_calibration_enable(ADC->adc_port); |
ADC的使能比較簡單,使能后ADC才能工作,這里再強調下,使能ADC不代表就開始了ADC轉換,而是ADC等到觸發(fā)信號才會轉換,關于觸發(fā)條件,請讀者看前面觸發(fā)源介紹。
ADC 帶有一個前置校準功能。在校準期間,ADC計算一個校準系數(shù),這個系數(shù)是應用于ADC內部的,它直到ADC下次掉電才無效。在校準期間,應用不能使用ADC,它必須等到校準完成。在A/D轉換前應執(zhí)行校準操作。通過軟件設置CLB=1來對校準進行初始化,在校準期間CLB位會一直保持1,直到校準完成,該位由硬件清0。
ADC使能后校準前比較要等待至少14個ADC時鐘周期,本實驗中就直接使用1ms延時了,是完全足夠的。
關于校準:一般建議ADC enable之后進行一次校準,但需要保證校準器件,ADC參考電壓一定要很穩(wěn)定,否則可能校準到一個錯誤的情況,這樣后續(xù)的ADC轉換反而不準確了,所以在一些特定情況下,校準也可以不加。 |
11.4.2輪訓方式獲取采樣值函數(shù)
ADC初始化好后,就可以進行采樣了,本實驗是通過輪訓方式進行ADC采樣,下面是輪訓方式獲取采樣值函數(shù)。
C uint16_t driver_adc_transform_polling(typdef_adc_ch_general *ADC,typdef_adc_ch_parameter *ADC_CH) { /*規(guī)則組采樣*/ if(ADC->adc_channel_group == ADC_REGULAR_CHANNEL) { /*設置規(guī)則組需要采樣的通道*/ adc_regular_channel_config(ADC->adc_port, 0, ADC_CH->adc_channel, ADC_CH->sample_time); /*軟件觸發(fā)規(guī)則組轉換*/ adc_software_trigger_enable(ADC->adc_port, ADC_REGULAR_CHANNEL); /*等待EOC置起*/ while(RESET == adc_flag_get(ADC->adc_port,ADC_FLAG_EOC)); /*清除EOC標志位*/ adc_flag_clear(ADC->adc_port,ADC_FLAG_EOC); /*將規(guī)則組轉換結果作為返回值*/ return ADC_RDATA(ADC->adc_port); } /*注入組采樣*/ else if(ADC->adc_channel_group == ADC_INSERTED_CHANNEL) { /*設置注入組需要采樣的通道*/ adc_inserted_channel_config(ADC->adc_port, 0, ADC_CH->adc_channel, ADC_CH->sample_time); /*軟件觸發(fā)注入組轉換*/ adc_software_trigger_enable(ADC->adc_port, ADC_INSERTED_CHANNEL); /*等待EOIC置起 */ while(RESET == adc_flag_get(ADC->adc_port,ADC_FLAG_EOIC)); /*清除EOIC標志位*/ adc_flag_clear(ADC->adc_port,ADC_FLAG_EOIC); /*將注入組轉換結果作為返回值*/ return ADC_IDATA0(ADC->adc_port); } return 0; } |
讀者可以讀以上代碼的注釋來分析這個函數(shù),強調下,判斷規(guī)則組轉換完成用EOC標志位,注入組用EOIC。另外這個函數(shù)返回值是16位,但如果使用了規(guī)則并行或注入并行的話,該函數(shù)還需要稍作調整,讀者可以思考下該如何修改?
11.4.3Power_detect ADC設置所需要的參數(shù)及IO口結構體定義
在bsp_adc.c中,對Power_detect_ADC設置所需要的參數(shù)及IO擴結構體進行了定義:
C typdef_adc_ch_general Power_detect_ADC= { .rcu_adc = RCU_ADC2,//ADC2的時鐘 .adc_psc = RCU_CKADC_CKAPB2_DIV6,//ADC2設置為APB2 6分頻 .adc_port = ADC2,//ADC口為ADC2 .adc_mode = ADC_MODE_FREE,//ADC模式為獨立模式 .adc_channel_group = ADC_REGULAR_CHANNEL,//使用規(guī)則組 .adc_scan_function = DISABLE,//關閉掃描模式 .adc_continuous_function = DISABLE,//關閉循環(huán)模式 .ch_count = 1,//轉換長度為1 .dma_parameter = {0},//不使用DMA .trigger_source = ADC0_1_2_EXTTRIG_REGULAR_NONE,//ADC觸發(fā)源選擇為軟件觸發(fā) .DMA_mode = DISABLE//不使用DMA }; //ADC通道參數(shù)配置,包括IO口,和對應通道以及采樣周期 typdef_adc_ch_parameter Power_detect_ch_parameter= { .rcu_port = RCU_GPIOF,//GPIOF時鐘 .port = GPIOF,//GPIO port .pin = GPIO_PIN_6,//PF6 .gpio_speed = GPIO_OSPEED_10MHZ,//PF6速度設置為10MHz .adc_channel = ADC_CHANNEL_4,//PF6是ADC2的通道4 .sample_time = ADC_SAMPLETIME_55POINT5//設置采樣周期為55.5 }; |
11.4.4Power_detect ADC初始化和讀Power_detect的具體實現(xiàn)函數(shù)
在bsp_adc.c中定義了Power_detect ADC初始化和讀Power_detect的具體實現(xiàn)函數(shù):
C uint16_t Power_detect_data = 0; void bsp_Power_detect_ADC_config() { driver_adc_config(&Power_detect_ADC,&Power_detect_ch_parameter); } void bsp_Power_detect_data_get() { Power_detect_data = driver_adc_transform_polling(&Power_detect_ADC,&Power_detect_ch_parameter); } |
11.4.5main函數(shù)實現(xiàn)
C int main(void) { driver_init();//延時函數(shù)初始化 bsp_uart_init(&BOARD_UART);//BOARD_UART串口初始化 bsp_Power_detect_ADC_config();//Power_detect ADC配置 while (1) { delay_ms(1000);//延時1s bsp_Power_detect_data_get();//獲取Power_detect數(shù)據(jù) printf(" the Power_detect data is %d \r\n", Power_detect_data);//打印Power_detect數(shù)據(jù) printf(" the Power voltage is %.2f V \r\n", (float)Power_detect_data/4096*3.3f*2);//輸出供電電壓值 } } |
本例程main函數(shù)首先進行了延時函數(shù)初始化,為了演示實驗結果,這里初始化了BOARD_UART串口,關于串口的使用,請讀者參考串口章節(jié),然后是Power_detect ADC配置。在主循環(huán)中實現(xiàn)每秒鐘進行一次Power_detect的ADC采樣,并將轉換結果打印出來。
11.5實驗結果
使用USB-TypeC線,連接電腦和板上USB to UART口后,配置好串口調試助手,即可看到Power_detect打印數(shù)據(jù)了。


本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關注聚沃科技官網
-
單片機
+關注
關注
6050文章
44687瀏覽量
641186 -
adc
+關注
關注
99文章
6567瀏覽量
546720 -
開發(fā)板
+關注
關注
25文章
5210瀏覽量
99126 -
GD32
+關注
關注
7文章
416瀏覽量
24661
發(fā)布評論請先 登錄
相關推薦
【星空派GD32F303開發(fā)板試用體驗】開箱+環(huán)境搭建
【星空派GD32F303開發(fā)板試用體驗】開箱+環(huán)境搭建
【星空派GD32F303開發(fā)板試用體驗】+板卡概覽
STM32CUBEMX開發(fā)GD32F303(10)----雙ADC輪詢模式掃描多個通道

STM32CUBEMX開發(fā)GD32F303(11)----ADC在DMA模式下掃描多個通道

STM32CUBEMX開發(fā)GD32F303(14)----IIC之配置OLED

GD32F303固件庫開發(fā)

【GD32F470紫藤派開發(fā)板使用手冊】第八講 ADC-規(guī)則組多通道采樣實驗

【GD32F303紅楓派開發(fā)板使用手冊】第五講 FMC-片內Flash擦寫讀實驗

【GD32F303紅楓派開發(fā)板使用手冊】第十二講 ADC-雙軸按鍵搖桿多通道循環(huán)采樣實驗

【GD32F303紅楓派開發(fā)板使用手冊】第十三講 ADC-內部溫度傳感器和參考電壓采樣實驗

【GD32F303紅楓派開發(fā)板使用手冊】第十六講 USART-DMA串口收發(fā)實驗

【GD32F303紅楓派開發(fā)板使用手冊】第二十講 SPI-SPI NAND FLASH讀寫實驗

評論