STM32ADC的工作原理
模/數(shù)轉換器
STM32F10x ADC特點
12位逐次逼近型的模擬數(shù)字轉換器。
最多帶3個ADC控制器
最多支持18個通道,可最多測量16個外部和2個內部信號源。
支持單次和連續(xù)轉換模式
轉換結束,注入轉換結束,和發(fā)生模擬看門狗事件時產生中斷。
通道0到通道n的自動掃描模式
自動校準
采樣間隔可以按通道編程
規(guī)則通道和注入通道均有外部觸發(fā)選項
轉換結果支持左對齊或右對齊方式存儲在16位數(shù)據(jù)寄存器
ADC轉換時間:最大轉換速率 1us。(最大轉換速度為1MHz,在ADCCLK=14M,采樣周期為1.5個ADC時鐘下得到。)
ADC供電要求:2.4V-3.6V
ADC輸入范圍:VREF- ≤ VIN ≤ VREF+
ADC引腳
☞STM32F10x系列芯片ADC通道和引腳對應關系
由下圖可見ADC1的通道0~通道17都有功能,而ADC2的通道16和通道17沒有作用,ADC3的通道9、通道14~通道17也沒有作用。
STM32通道組
①規(guī)則通道組:相當正常運行的程序。最多16個通道。
規(guī)則通道和它的轉換順序在ADC_SQRx寄存器中選擇,規(guī)則
組轉換的總數(shù)應寫入ADC_SQR1寄存器的L[3:0]中
② 注入通道組:相當于中斷。最多4個通道。
注入組和它的轉換順序在ADC_JSQR寄存器中選擇。注入組
里轉化的總數(shù)應寫入ADC_JSQR寄存器的L[1:0]中
STM32F1的ADC的各通道可以單次模式執(zhí)行,連續(xù)模式執(zhí)行,掃描或者間斷模式執(zhí)行。
規(guī)則通道組
含有注入通道的規(guī)則通道組
☞單次轉化
單次轉換模式下,ADC只執(zhí)行一次轉換。該模式既可通過設置ADC_CR2寄存器的ADON位(只
適用于規(guī)則通道)啟動也可通過外部觸發(fā)啟動(適用于規(guī)則通道或注入通道),這時CONT位為0。
一旦選擇通道的轉換完成:
● 如果一個規(guī)則通道被轉換:
─ 轉換數(shù)據(jù)被儲存在16位ADC_DR寄存器中
─ EOC(轉換結束)標志被設置
─ 如果設置了EOCIE,則產生中斷。
● 如果一個注入通道被轉換:
─ 轉換數(shù)據(jù)被儲存在16位的ADC_DRJ1寄存器中
─ JEOC(注入轉換結束)標志被設置
─ 如果設置了JEOCIE位,則產生中斷。
☞連續(xù)轉換模式
在連續(xù)轉換模式中,當前面ADC轉換一結束馬上就啟動另一次轉換。(連續(xù)轉換會自動開啟下一次轉換)此模式可通過外部觸發(fā)啟
動或通過設置ADC_CR2寄存器上的ADON位啟動,此時CONT位是1。
每個轉換后:
● 如果一個規(guī)則通道被轉換:
─ 轉換數(shù)據(jù)被儲存在16位的ADC_DR寄存器中
─ EOC(轉換結束)標志被設置
─ 如果設置了EOCIE,則產生中斷。
● 如果一個注入通道被轉換:
─ 轉換數(shù)據(jù)被儲存在16位的ADC_DRJ1寄存器中
─ JEOC(注入轉換結束)標志被設置
─ 如果設置了JEOCIE位,則產生中斷。
☞掃描模式
此模式用來掃描一組模擬通道。掃描模式可通過設置ADC_CR1寄存器的SCAN位來選擇。一旦這個位被設置,ADC掃描所有被ADC_SQRX寄存器(對規(guī)則通道)或ADC_JSQR(對注入通道)選中的所有通道。在每個組的每個通道上執(zhí)行單次轉換。在每個轉換結束時,同一組的下一個通道被自動轉換。如果設置了CONT位,轉換不會在選擇組的最后一個通道上停止,而是再次從選擇組的第一個通道繼續(xù)轉換。如果設置了DMA位,在每次EOC后,DMA控制器把規(guī)則組通道的轉換數(shù)據(jù)傳輸?shù)絊RAM中。而注入通道轉換的數(shù)據(jù)總是存儲在ADC_JDRx寄存器中。
ADC中斷
規(guī)則和注入組轉換結束時能產生中斷,當模擬看門狗狀態(tài)位被設置時也能產生中斷。它們都有
獨立的中斷使能位。
注: ADC1 和 ADC2 的中斷映射在同一個中斷向量上,而 ADC3 的中斷有自己的中斷向量。
ADC_SR寄存器中有2個其他標志,但是它們沒有相關聯(lián)的中斷:
● JSTRT(注入組通道轉換的啟動)
● STRT(規(guī)則組通道轉換的啟動)
ADC 時鐘
由時鐘控制器提供的ADCCLK時鐘和PCLK2(APB2時鐘)同步。RCC控制器為ADC時鐘提供一個
專用的可編程預分頻器.注:不要讓ADC時鐘超過14MHz,否則可能不準。
可編程的通道采樣時間
ADC使用若干個ADC_CLK周期對輸入電壓采樣,采樣周期數(shù)目可以通過ADC_SMPR1和
ADC_SMPR2寄存器中的SMP[2:0]位更改。每個通道可以分別用不同的時間采樣。
總轉換時間如下計算:
T(CONV) = 采樣時間+ 12.5個周期
例如:
當ADCCLK=14MHz,采樣時間為1.5周期
T(CONV) = 1.5 + 12.5 = 14周期 = 1μs
ADC_SMPR1寄存器和ADC_SMPR2寄存器用來設置通道0~17這18個通道
ADC采樣時間——可編程的采樣時間
ADC_SQR1/SQR2/SQR3規(guī)則序列寄存器
ADC_JSQR注入系列寄存器
ADC_SR狀態(tài)寄存器
常用庫函數(shù)
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);ADC的初始化函數(shù)
void ADC_DeInit(ADC_TypeDef* ADCx);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);ADC使能函數(shù)
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);中斷配置函數(shù)
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);軟件啟動轉換函數(shù)
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);配置規(guī)則通道
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);ADC獲取轉換結果函數(shù)
校準函數(shù):
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
例如:
ADC_ResetCalibration(ADC1); //使能復位校準
while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校準結束
ADC_StartCalibration(ADC1); //開啟AD校準
while(ADC_GetCalibrationStatus(ADC1)); //等待校準結束
typedef struct
{
uint32_t ADC_Mode;//ADC模式:配置ADC_CR1寄存器的位[19:16] :DUALMODE[3:0]位
FunctionalState ADC_ScanConvMode; //是否使用掃描模式。ADC_CR1位8:SCAN位
FunctionalState ADC_ContinuousConvMode; //單次轉換OR連續(xù)轉換:ADC_CR2的位1:CONT uint32_t ADC_ExternalTrigConv; //觸發(fā)方式:ADC_CR2的位[19:17] :EXTSEL[2:0]
uint32_t ADC_DataAlign; //對齊方式:左對齊還是右對齊:ADC_CR2的位11:ALIGN
uint8_t ADC_NbrOfChannel;//規(guī)則通道序列長度:ADC_SQR1的位[23:20]: L[3:0]
}ADC_InitTypeDef;
例:
void ADC_Init(ADC_TypeDef*ADCx,ADC_InitTypeDef*ADC_InitStruct)
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //獨立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //不開啟掃描
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //單次轉換模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //觸發(fā)軟件
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC數(shù)據(jù)右對齊
ADC_InitStructure.ADC_NbrOfChannel = 1; //順序進行規(guī)則轉換的ADC通道的數(shù)目
ADC使能函數(shù)ADC_Cmd()
例如:ADC_Cmd(ADC1,ENABLE);//使能指定的ADC1
ADC使能軟件轉換函數(shù)ADC void ADC_SoftwareStartConvCmd();
例如:ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1的軟件轉換啟動
ADC規(guī)則通道配置函數(shù)voidADC_RegularChannelConfig()
例如:ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);//在ADC1的通道1,規(guī)則序列中的第1個轉換,采樣時間。ADC_RegularChannelConfig(用哪個ADC,哪個通道, 通道在規(guī)則序列中的序號, 采樣時間);
ADC獲取轉換結果函數(shù)ADC_GetConversionValue();如ADC_GetConversionValue(ADC1);//獲取ADC1轉換結果
實驗一:ADC1的通道1(PA1)進行單次轉換
目的:使用庫函數(shù)的函數(shù)來設定使用ADC1的通道1進行A/D轉換。
ADC的配置過程如下:
①開啟PA口時鐘和ADC1時鐘,設置PA1為模擬輸入。
GPIO_Init();
APB2PeriphClockCmd();
② 復位ADC1,同時設置ADC1分頻因子。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_DeInit(ADC1);
③ 初始化ADC1參數(shù),設置ADC1的工作模式以及規(guī)則序列的相關信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
④ 使能ADC并校準。
ADC_Cmd(ADC1, ENABLE); //ADC使能函數(shù)
校準使用校準函數(shù)
⑤ 配置規(guī)則通道參數(shù):
ADC_RegularChannelConfig();
ADC1的通道1的配置方法:ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5)
⑥開啟軟件轉換:
ADC_SoftwareStartConvCmd(ADC1);
⑦等待轉換完成,讀取ADC值。
ADC_GetConversionValue(ADC1);//獲取ADC1的轉換結果
將上面七個步驟的功能代碼寫在兩個函數(shù)中即可實現(xiàn)功能,分別是函數(shù)void Adc_Init(void);和函數(shù)u16 Get_Adc(u8 ch);
將上面步驟一到步驟四的程序功能代碼寫在void Adc_Init(void);函數(shù)中。
獲取轉換結果即將實現(xiàn)步驟五到步驟七的功能代碼寫在u16 Get_Adc(u8 ch);函數(shù)中
多次調用u16 Get_Adc(u8 ch)函數(shù)讀取ADC1的轉換結果,再求平均值,將功能代碼寫在u16 Get_Adc_Average(u8 ch,u8 times)函數(shù)中
STM32實現(xiàn)對12V電壓的檢測
我們現(xiàn)在需要用STM32對12V電壓進行檢測,判斷其是否正確上電。我打算利用STM32的ADC功能,但12V超過了STM32能承受的范圍,我們可以用電阻簡單分壓成3.3V,然后用STM32的ADC引腳直接采樣,判斷。不要讓ADC腳接到5V以上的的電壓,會燒壞引腳。
|