學習建議:推薦搭配 江協科技 AD單通道 AD多通道一起食用!!!!
【STM32入門教程-2023版 細致講解 中文字幕】https://www.bilibili.com/video/BV1th411z7sn?p=22&vd_source=66c03c3ecc640bbe982dc3d48bfd8841
AD單通道(實驗)
- 初始化流程:
開啟時鐘 → 配置 GPIO 為模擬輸入 → 配置規則組通道 → 初始化 ADC 結構體 → 開啟 ADC 電源 → 校準 ADC。 - 單次轉換流程:
軟件觸發轉換 → 等待EOC
標志位 → 讀取轉換結果。
有關配置的庫函數
1. RCC_ADCCLKConfig
- 功能:配置 ADC 的時鐘分頻器,確定 ADC 工作時鐘(ADCCLK)。
- 參數:可選分頻系數為 2、4、6、8,輸入時鐘為 APB2 的 72MHz 時鐘。
- 示例:若選擇 6 分頻,ADCCLK = 72MHz / 6 = 12MHz。
- 作用:確保 ADC 工作在合適的時鐘頻率下,保證轉換精度和穩定性。
- 在RCC庫函數中,配置ADC工作時鐘。
2.電源與校準函數
ADC_Cmd
- 功能:開啟或關閉 ADC 電源。
- 參數:
ENABLE
啟動 ADC,DISABLE
關閉。
- 校準函數組(需按順序調用):
ADC_ResetCalibration
:復位校準寄存器。ADC_GetResetCalibrationStatus
:等待復位校準完成(通過循環檢測標志位)。ADC_StartCalibration
:啟動校準。ADC_GetCalibrationStatus
:等待校準完成(通過循環檢測標志位)。- 作用:減小 ADC 轉換誤差,需在初始化后調用。
3.中斷與 DMA 相關函數
ITConfig
:開啟或關閉 ADC 中斷(如模擬看門狗中斷)。NVIC_Init
:配置中斷優先級(需結合ITConfig
使用)。DMA_Cmd
:開啟 DMA 傳輸(用于多通道數據搬運,會議中未深入講解)。
4.觸發與轉換控制函數
ADC_SoftwareStartConvCmd
- 功能:軟件觸發 ADC 開始轉換(適用于單次轉換模式)。
- 參數:
ENABLE
觸發轉換,DISABLE
關閉。
- ADC_GetSoftwareStartConvStatus
- 不能獲取軟件觸發轉換狀態,因為當有軟件觸發標志時,一旦開始轉化就會將軟件觸發標志位清零,不會通過該函數獲得是否轉化完成。
ADC_GetFlagStatus
- 功能:獲取轉換狀態標志位。
- 關鍵參數
ADC_FLAG_EOC
:規則組轉換完成標志位(轉換結束后硬件置 1)。
- 用途:通過檢測
EOC
標志位判斷轉換是否完成,而非使用ADC_GetSoftwareStartConvStatus
(該函數僅返回觸發狀態,與轉換完成無關)。
5.配置間斷模式函數
- ADC_DiscModeChannelCountConfig
- 每隔幾個通道間斷一次
- ADC_DiscModeCmd
- 是否開啟間斷模式
6.規則組通道配置
- ADC_RegularChannelConfig
- 功能:配置規則組通道參數,如通道號、序列位置、采樣時間。
- 參數
ADCx
:ADC 外設(如ADC1
)。ADC_Channel
:通道編號(如 PA0 對應ADC_Channel_0
)。Rank
:序列位置(1~16,非掃描模式下僅需設為 1)。ADC_SampleTime
:采樣時間(影響轉換速度和穩定性,可選短 / 中 / 長周期)。
7.其他
-
ADC_ExternalTrigConvCmd
- 外部觸發轉換控制 ,就是是否允許外部觸發轉換
-
ADC_GetConversionValue
- 功能:讀取規則組通道的轉換結果(16 位無符號整數)。
- 返回值:轉換后的數字量,需結合參考電壓計算實際模擬值。
-
ADC_GetDualModeConversionValue
- ADC獲取雙模式轉換值,雙ADC模式讀取轉化結果的函數
-
ADC_TempSensorVrefintCmd
- ADC溫度傳感器,內部參考電壓控制,用來開啟內部的兩個通道。
8.注入組與模擬看門狗函數
-
注入組函數:帶
Injected
前綴的函數(如ADC_InjectedChannelConfig
),用于配置緊急通道(會議中未使用)。 -
模擬看門狗函數
ADC_AnalogWatchdogCmd
:啟動模擬看門狗,監測輸入電壓是否超出閾值。ADC_AnalogWatchdogThresholdsConfig
:設置電壓閾值(高 / 低閾值)。
-
ADC_AnalogWatchdogSingleChannelConfig
- 配置看門的通道
AD單通道部分主要代碼
// AD.c
#include "stm32f10x.h" // Device headervoid AD_Init(void)
{//1.開始時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//2. 配置ADC時鐘信號//只能使用6 或者 8 分頻,因為有限制RCC_ADCCLKConfig(RCC_PCLK2_Div6);//3.配置gpio口 //初始化gpioinit參數中的結構體GPIO_InitTypeDef GPIO_InitStructure;//將gpio口設置為模擬輸入模式,就是io口不起作用不會影響數據轉化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);//4.配置規則組通道ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//5.初始化ADC模塊ADC_InitTypeDef ADC_InitStruct;//是否連續轉化ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//對齊方式ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//外部觸發方式,使用軟件觸發,所以配置為ADC_ExternalTrigConv_NoneADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;ADC_InitStruct.ADC_NbrOfChannel = 1;//配置連續掃描ADC_InitStruct.ADC_ScanConvMode = DISABLE;ADC_Init(ADC1, &ADC_InitStruct);//6. 開啟ADC總開關ADC_Cmd(ADC1, ENABLE);//7.校準ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1) == SET);}
//啟動轉換,獲取結果函數
uint16_t AD_GetValve(void)
{//內部軟件啟動轉換ADC_SoftwareStartConvCmd(ADC1, ENABLE);//查看是否轉化完成//查看標志位,轉化完成會將EOC標志位置一while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//讀取數據return ADC_GetConversionValue(ADC1);
}
AD多通道實現
多通道采集實現思路探討
- 掃描模式結合 DMA :利用列表填充四個通道觸發轉換可實現多通道,但存在數據覆蓋問題,最好配合 DMA 實現,講完 DMA 后再嘗試。
- 手動轉運數據問題 :掃描模式下單個通道轉換完成無標志位和中斷,只有整個列表轉換完才有 EOC 標志位和中斷,易造成數據覆蓋丟失;且 AD 轉換快,手動轉運數據對程序要求高,操作困難。
- 間斷模式手動轉運 :可使用間斷模式,每轉換一個通道暫停,手動轉運數據后再繼續,但因無標志位需靠 delay 延時保證轉換完成,不省心且效率低,暫不推薦。
單次轉換非掃描模式實現AD多通道
- 具體實現方式 :每次觸發轉換前手動更改列表第一個位置的通道,如依次寫入通道 0、1、2、3 等,觸發轉換等待讀值,就能實現多通道轉換。
AD多通道部分代碼
//AD.c
#include "stm32f10x.h" // Device headervoid AD_Init(void)
{//1.開始時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//2. 配置ADC時鐘信號//只能使用6 或者 8 分頻,因為有限制RCC_ADCCLKConfig(RCC_PCLK2_Div6);//3.配置gpio口 //初始化gpioinit參數中的結構體GPIO_InitTypeDef GPIO_InitStructure;//將gpio口設置為模擬輸入模式,就是io口不起作用不會影響數據轉化GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//5.初始化ADC模塊ADC_InitTypeDef ADC_InitStruct;//是否連續轉化ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//對齊方式ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//外部觸發方式,使用軟件觸發,所以配置為ADC_ExternalTrigConv_NoneADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;ADC_InitStruct.ADC_NbrOfChannel = 1;//配置連續掃描ADC_InitStruct.ADC_ScanConvMode = DISABLE;ADC_Init(ADC1, &ADC_InitStruct);//6. 開啟ADC總開關ADC_Cmd(ADC1, ENABLE);//7.校準ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1) == SET);}
//使用單次轉化,非掃描模式實現AD多通道
//啟動轉換,獲取結果函數
uint16_t AD_GetValve(uint8_t ADC_Channel)
{//配置規則組通道ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);//內部軟件啟動轉換ADC_SoftwareStartConvCmd(ADC1, ENABLE);//查看是否轉化完成//查看標志位,轉化完成會將EOC標志位置一while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//讀取數據return ADC_GetConversionValue(ADC1);
}
//main.c#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"
uint16_t value0;
uint16_t value1;
uint16_t value2;
uint16_t value3;int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1, 1, "V0:");OLED_ShowString(2, 1, "V1:");OLED_ShowString(3, 1, "V2:");OLED_ShowString(4, 1, "V3:");while(1){value0 = AD_GetValve(ADC_Channel_0);value1 = AD_GetValve(ADC_Channel_1);value2 = AD_GetValve(ADC_Channel_2);value3 = AD_GetValve(ADC_Channel_3);OLED_ShowNum(1, 4, value0, 4);OLED_ShowNum(2, 4, value1, 4);OLED_ShowNum(3, 4, value2, 4);OLED_ShowNum(4, 4, value3, 4);Delay_ms(100);}
}