目錄
一、ADC介紹
二、ADC主要特征
三、ADC框圖
? ? 1. ?????外部觸發轉換??
? ? ?2. 轉換模式
? ? ?3. 輸入通道
? ? ? ? ? ? ? 4.? 邏輯框圖
?四、校準
五、數據對齊
六、AD轉換步驟
七、AD_Init(單通道AD轉換)初始化函數配置
DMA:?
adc_dma_mode_enable(ADC0);
????????這段代碼是用來使能ADC的DMA(Direct Memory Access)模式。DMA模式允許ADC在轉換完成后,將轉換結果直接傳輸到內存中,而不需要CPU的干預。這對于高速數據傳輸和數據處理來說是很有用的,因為可以減輕CPU的負擔,提高系統效率。
????????在這個特定的代碼中,因為希望通過DMA方式將ADC的轉換結果傳輸到內存,以便后續的數據處理或存儲。DMA模式的使用通常涉及到DMA配置的詳細設置,包括目標地址、數據長度等,這些設置在其他部分的代碼中進行。
一、ADC介紹
? ? ? ? 1. 12位ADC是一種逐次逼近型模擬數字轉換器。它有多達18個通道,可測量16個外部和2個內部信號源。
? ? ? ?rcu_periph_clock_enable(RCU_ADC0);開啟時鐘
? ? ? ? 2. ADC的輸入時鐘不得超過14MHz,它是由PCLK2經分頻產生的。
所以在初始化函數中往往先進行?rcu_adc_clock_config(RCU_CKADC_CKAHB_DIV10);
這句話的意思就是進行10分頻(這個是在GD32A503x中,不同的芯片有所不同)。
#define RCU_CKADC_CKAHB_DIV10 ? ? ? ? ? CFG2_ADCPSC(8) ? ? ? ? ? ? ? ? ?
? ? /*!< ADC prescaler select CK_AHB/10 */在GD32中時鐘由AHB分配。
所以底層函數中:
??rcu_adc_clock_config(RCU_CKADC_CKAHB_DIV10);為10MHz
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)
/*RCC_PCLK2: defines the ADC clock divider. This clock is derived from the APB2 clock (PCLK2).*/
//eg:
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//選擇時鐘6分頻,ADCCLK = 72MHz / 6 = 12MHz
????????但是需要注意的是,如下圖,ADCCLK最大14MHz。
?初始化IO口:(可封裝在函數中)
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_10 | GPIO_PIN_11);
gpio_mode_set(GPIOE, GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11| GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14);
gpio_mode_set(GPIOB, GPIO_MODE_ANALOG,GPIO_PUPD_NONE,GPIO_PIN_1);
//模擬輸入模式GPIO_MODE_ANALOG
????????這部分代碼配置了三組GPIO口(分別是GPIOC和GPIOE和GPIOB),將它們設置為模擬輸入模式,同時禁用了上拉和下拉電阻。這是因為ADC通道需要連接到模擬信號,而不需要上拉或下拉電阻對這些信號產生影響。
二、ADC主要特征
????????1. ADC可以將引腳上連續變化的模擬電壓轉換為內存中存儲的數字變量,建立模擬電路到數字電路的橋梁
????????2. 12位逐次逼近型ADC,1us轉換時間
????????3. 輸入電壓范圍:0~3.3V,轉換結果范圍:0~4095
????????4. 18個輸入通道,可測量16個外部和2個內部信號源
????????5. 規則組和注入組兩個轉換單元
????????6. 模擬看門狗自動監測輸入電壓范圍
三、ADC框圖
GD32的圖和STM32:?
? ? 1. ?????外部觸發轉換?
? ? ? 2. 轉換模式
????????單次轉換模式下,ADC只執行一次轉換。該模式既可通過設置ADC_CR2寄存器的ADON位(只適用于規則通道)啟動也可通過外部觸發啟動(適用于規則通道或注入通道),這時CONT位為0。 一旦選擇通道的轉換完成。
????????在連續轉換模式中,當前面ADC轉換一結束馬上就啟動另一次轉換。此模式可通過外部觸發啟動或通過設置ADC_CR2寄存器上的ADON位啟動,此時CONT位是1。
? ? ? ? 總的來說就是:單次模式、連續模式:ADC單通道要求進行一次ADC轉換時配置為單次模式使能,這樣ADC的這個通道轉換一次后就停止轉換。要求進行連續ADC轉換時配置為連續模式使能,這樣ADC的這個通道轉換一次后接著進行下一次。?掃描模式:對應多個ADC通道的情況,每個通道依次進行轉換。
? ? ? 3. 輸入通道(觀察手冊)
通道 | ADC1 | ADC2 | ADC3 |
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 | PF6 |
通道5 | PA5 | PA5 | PF7 |
通道6 | PA6 | PA6 | PF8 |
通道7 | PA7 | PA7 | PF9 |
通道8 | PB0 | PB0 | PF10 |
通道9 | PB1 | PB1 | |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | |
通道15 | PC5 | PC5 | |
通道16 | 溫度傳感器 | ||
通道17 | 內部參考電壓 |
? ? ?4.? 邏輯框圖
???????????規則組最多轉換16通道,注入組最多轉換4通道,但是規則通道為“一次可以點16個菜,但是一次只能上一個菜”,因為規則通道的數據寄存器僅僅為16位,而注入通道為“一次可以點4個菜,但一次可以最多上4個菜”。
?ADC初始化配置:
1. 配置模式://獨立模式adc_mode_config(ADC_MODE_FREE);
2. 對齊方式
?? ?//右對齊
?? ?adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
數據對齊的方式:左對齊、右對齊等方式。對于右對齊方式,ADC轉換結果的低位存儲在寄存器的低地址處,而高位則存儲在寄存器的高地址處。
ADC數據對齊方式指定了ADC轉換結果在寄存器中的存儲方式。對于右對齊方式,ADC轉換結果的低位存儲在寄存器的低地址處,而高位則存儲在寄存器的高地址處。這種對齊方式是一種常見的選擇,便于處理和理解。對齊方式的選擇可能與使用的數據類型和后續的數據處理有關。一般而言,如果你希望ADC轉換結果的低位直接對應于采樣的最低位,方便直接使用整數數據類型處理,那么右對齊方式是一個合適的選擇。對于上述代碼片段中的 adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);,它是為 ADC0 配置右對齊方式。這樣設置可以確保 ADC 轉換結果按照右對齊方式存儲,使得數據處理更為方便。
3. 開啟連續模式和掃描模式
?adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);
?adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);
連續模式(Continuous Mode):在連續模式下,ADC會不停地進行模擬信號的轉換,而不需要外部觸發。這種模式適用于需要實時、連續采樣的應用,比如實時監測、數據采集等。
連續模式允許ADC持續地對設置的正常通道序列進行轉換,無需每次都手動觸發。這對于周期性的數據采集或需要持續監測的應用非常有用。掃描模式(Scan Mode):在掃描模式下,ADC會按照預先配置的正常通道順序依次進行轉換。每次轉換完成后,ADC會自動切換到下一個正常通道,直到所有通道都被轉換完成。
掃描模式適用于多通道的采樣需求。通過在代碼中配置正常通道序列,可以按照特定的順序對多個信號進行采樣,而不需要手動切換通道。
4. 規則通道個數
?adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,ADC_CHNL_NUM);
adc_channel_length_config 函數用于設置 ADC 的正常通道組中的通道個數,其中:ADC0 是指定的 ADC 外設。
ADC_REGULAR_CHANNEL 表示正常通道組。
ADC_CHNL_NUM 是要配置的通道個數。
在嵌入式系統中,ADC 通道組是按照一定的規律或順序進行采樣的。通常,正常通道組用于按照預定順序對一組通道進行采樣。通過設置通道個數,你可以指定在一次轉換中,ADC 將采樣多少個通道。在這里,ADC_CHNL_NUM 的值決定了正常通道組中的通道個數。
?? ? ? 但是規則組最多轉換16通道,注入組最多轉換4通道,但是規則通道為“一次可以點16個菜,但是一次只能上一個菜”,因為規則通道的數據寄存器僅僅為16位,而注入通道為“一次可以點4個菜,但一次可以最多上4個菜”。
所以緊接著需要進行轉換順序的配置:
adc_regular_channel_config(ADC0,0,ADC_CHANNEL_12,ADC_SAMPLETIME_479POINT5);
為什么需要進行這一系列操作了,是因為:?
????????總的來說,模擬量是連續的、實數值形式的信號,而數字量是對模擬信號進行采樣和量化后的離散數值信號。在監測落肥的應用中,傳感器可能輸出模擬信號,而ADC負責將這些模擬信號轉換為微控制器或處理器能夠理解的數字信號,以便進行后續的處理和分析。
在監測落肥的場景中,涉及到的是模擬量和數字量的概念。下面對這兩者進行簡單的解釋:模擬量(Analog Signal):模擬量是指在一定時間內,信號的數值可以連續取任意值的信號。在農業領域,例如監測落肥量,模擬量可以是液體流量、氣體壓力等。這些信號的數值可以是任何在一定范圍內的實數值,而不是離散的數值。
在這個場景中,模擬量可能對應于精確的落肥液流量或其他液體特性,這些物理量通過傳感器測量并以模擬形式呈現。
數字量(Digital Signal):數字量是指信號的數值以離散的形式表示。通常,模擬信號需要通過模數轉換(ADC)轉換為數字信號,以便在數字系統中進行處理和存儲。
在監測落肥量的場景中,通過ADC轉換后,得到的數字量可能是一個表示液體流量、壓力等的數字值。數字化后的信號可以在數字系統中進行處理、存儲、傳輸和顯示。
?四、校準
????????ADC有一個內置自校準模式。校準可大幅減小因內部電容器組的變化而造成的準精度誤差。在校準期間,在每個電容器上都會計算出一個誤差修正碼(數字值),這個碼用于消除在隨后的轉換中每個電容器上產生的誤差。特別需要注意:建議在每次上電后執行一次校準。簡單說,這就是個固定流程,stm32要求這么處理:
// ADC 復位校準
adc_calibration_enable(ADC0);
????????這行代碼通過調用 adc_calibration_enable
函數啟用了 ADC 的復位校準。ADC 校準是在初始化過程中的一項重要步驟,它有助于提高 ADC 轉換的準確性。校準通常在 ADC 啟動之后進行,確保 ADC 能夠對模擬輸入進行準確的數字化轉換。
????????需要注意的是,這個校準步驟只執行一次,通常在初始化時進行。在代碼中,你可以看到在啟用 ADC 之后等待了一段時間:這是為了等待 ADC 穩定,確保校準在 ADC 開啟后充分生效。
adc_enable(ADC0);
delay_xms(1);
adc_calibration_enable(ADC0);
? ? 示例代碼如下:
ADC_ResetCalibration(ADC1); //固定流程,內部有電路會自動執行校準while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);
五、數據對齊
? ? ? ? 左對齊與右對齊
?
六、AD轉換步驟
? ? ? ? 采樣、保持、量化、編碼
? ? ? ? ADC總轉換時間:TCONV = 采樣時間+ 12.5個周期
????????例如: 當ADCCLK=14MHz,采樣時間為1.5周期 TCONV = 1.5 + 12.5 = 14周期 = 1μs
? ? ? ? 為什么需要保持?
? ? ? ??因為AD轉換中量化、編碼需要一定的轉換時間,在這個時間內輸入電壓如果還在不斷變化,那么就無法定位電壓,所以往往在量化編碼前引入采樣開關,比如通過加入一個小的電容來存儲電壓。
最后就是使能ADC,這樣就初始化完成了:
//使能軟件觸發ADC 轉換?adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);
這樣,ADC 就可以按照預定的通道順序執行正常通道的連續掃描轉換
七、AD_Init(單通道AD轉換)初始化函數配置
????????1.使能外設時鐘:開啟ADC1的時鐘、開啟GPIO的時鐘
? ? ? ? 2.設置ADC的時鐘,選擇時鐘分頻
/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //開啟ADC1的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘/*設置ADC時鐘*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);
? ? ? ? 3.規則組通道配置????????
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
? ? ? ? 4.GPIO初始化、ADC初始化配置:
GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure; //定義結構體變量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,選擇獨立模式,即單獨使用ADC1ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //數據對齊,選擇右對齊ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部觸發,使用軟件觸發,不需要外部觸發ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //連續轉換,失能,每轉換一次規則組序列后停止ADC_InitStructure.ADC_ScanConvMode = DISABLE; //掃描模式,失能,只轉換規則組的序列1這一個位置ADC_InitStructure.ADC_NbrOfChannel = 1; //通道數,為1,僅在掃描模式下,才需要指定大于1的數,在非掃描模式下,只能是1ADC_Init(ADC1, &ADC_InitStructure); //將結構體變量交給ADC_Init,配置ADC1
? ? ? ? 5.ADC使能
? ? ? ? 6.ADC校準
/*ADC使能*/ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC開始運行/*ADC校準*///先將ADC1校準功能恢復到默認值,然后再初始化ADC1。ADC_ResetCalibration(ADC1); //固定流程,內部有電路會自動執行校準while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);
????????AD多通道轉換只需修改通道配置即可:
? ? ? ? EOC:轉換結束位,該位由硬件在規則或者注入通道組轉換結束時置1,由軟件清除或者讀取數據寄存器后自動清除,那么等待EOC標志位置1即等待AD轉換完成。
/*** 函 數:獲取AD轉換的值* 參 數:ADC_Channel 指定AD轉換的通道,范圍:ADC_Channel_x,其中x可以是0/1/2/3* 返 回 值:AD轉換的值,范圍:0~4095*/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5); //在每次轉換前,根據函數形參靈活更改規則組的通道1ADC_SoftwareStartConvCmd(ADC1, ENABLE); //軟件觸發AD轉換一次while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC標志位,即等待AD轉換結束return ADC_GetConversionValue(ADC1); //讀數據寄存器,得到AD轉換的結果
}