(stm32f103学习总结)—ADC模数转换实验
一、STM32F1 ADC介紹
TM32F103 系列一般都有 3 個 ADC,這些 ADC 可以獨立使用,也可 以使用雙重(提高采樣率)。STM32F1 的 ADC 是 12 位逐次 逼近型的模擬數字轉換器。它具有多達 18個復用通道,可測量來自16 個外部源、2 個內部源信號。 這些通道的 A/D 轉換可 以單次、連續(xù)、掃描或間斷模式執(zhí)行。ADC 的結果可以左對齊或右對齊 方式存儲在 16 位數據寄存器中。ADC具有模擬看門狗特性,允許應用程 序檢測輸入電壓是否超出用戶定義的閥值上限或者下限。
1.2 STM32F1 ADC結構框圖
STM32F1 ADC擁有這么多功能,是由ADC內部結構所決定。要更好的理 解STM32F1的ADC,就需要了解它內部的結構。如下圖所示:(大家 也可以查看《STM32F10x中文參考手冊》-11模數轉換器(ADC)章-ADC功 能說明)。
(1)標號1:電壓輸入引腳
ADC輸入電壓范圍為: VREF- ≤ VIN ≤ VREF+。由 VREF-、 VREF+ 、 VDDA 、 VSSA這四個外部引腳決定。通常我們把 VSSA和 VREF-接地 ,把 VREF+和 VDDA 接 3.3V,因此ADC的輸入電壓范圍為:0~3.3V。我 們使用的開發(fā)板ADC輸入電壓范圍為0~3.3V。
(2)標號2:輸入通道
STM32 的 ADC的輸入通道多達 18 個,其中外部的 16 個通道就是框 圖中的 ADCx_IN0、ADCx_IN1...ADCx_IN5(x=1/2/3,表示ADC數),通 過這16個外部通道可以采集模擬信號。這 16 個通道對應著不同的 IO 口, 具體是哪一個 IO 口可以從數據手冊查詢到,也可以從下圖查 看,同樣我們在開發(fā)板芯片原理圖內也給大家標注了。其中 ADC1 還有2 個內部通道:ADC1 的通道16連接到了芯片內部的溫度傳感器,通道17連 接到了內部參考電壓 VREFINT。ADC2 和ADC3的通道 16、 17全部連接到 了內部的 VSS。
(3)標號3:通道轉換順序
外部的 16 個通道在轉換的時候可分為2組通道:規(guī)則通道組和注入 通道組,其中規(guī)則通道組最多有16路,注入通道組最多有 4 路。 規(guī)則通道組:從名字來理解,規(guī)則通道就是一種規(guī)規(guī)矩矩的通道,類 似于正常執(zhí)行的程序,通常我們使用的都是這個通道。 注入通道組:從名字來理解,注入即為插入,是一種不安分的通道, 類似于中斷。當程序正常往下執(zhí)行時,中斷可以打斷程序的執(zhí)行。同樣 如果在規(guī)則通道轉換過程中,有注入通道插入,那么就要先轉換完注入 通道,等注入通道轉換完成后再回到規(guī)則通道的轉換流程。 每個組包含一個轉換序列,該序列可按任意順序在任意通道上完成。 例如,可按以下順序對序列進行轉換: ADC_IN3、ADC_IN8、 ADC_IN2、 ADC_IN2、 ADC_IN0、 ADC_IN2、 ADC_IN2、 ADC_IN15。
(4)標號4:觸發(fā)源(外部觸發(fā)和軟件觸發(fā))
選擇好輸入通道,設置好轉換順序,接下來就可以開始轉換。要開啟 ADC轉換,可以直接設置ADC 控制寄存器ADC_CR2 的 ADON位為1,即使能 ADC。當然ADC還支持外部事件觸發(fā)轉換,觸發(fā)源有很多,具體選擇哪一 種觸發(fā)源,由 ADC 控制寄存器2:ADC_CR2 的 EXTSEL[2:0]和 JEXTSEL[2:0]位來控制。EXTSEL[2:0]用于選擇規(guī)則通道的觸發(fā)源, JEXTSEL[2:0]用于選擇注入通道的觸發(fā)源。選定好觸發(fā)源之后,觸發(fā)源 是否要激活,則由 ADC 控制寄存器ADC_CR2 的 EXTTRIG 和 JEXTTRIG 這兩位來激活。 如果使能了外部觸發(fā)事件,我們還可以通過設置 ADC 控制寄存器 2:ADC_CR2 的EXTEN[1:0]和 JEXTEN[1:0]來控制觸發(fā)極性,可以有 4 種 狀態(tài),分別是:禁止觸發(fā)檢測、上升沿檢測、下降沿檢測以及上升沿和 下降沿均檢測。
(5)標號5:ADC時鐘
ADC 輸入時鐘 ADC_CLK 由 APB2經過分頻產生,最大值是14MHz,分 頻因子由 RCC 時鐘配置寄存器 RCC_CFGR 的位 15:14 ADCPRE[1:0]設置 ,可以是 2/4/6/8 分頻,注意這里沒有 1 分頻。我們知道APB2總線時 鐘為72M,而ADC最大工作頻率為14M,所以一般設置分頻因子為6,這樣 ADC的輸入時鐘為12MHz。
ADC要完成對輸入電壓的采樣需要若干個ADC_CLK周期,采樣的周期數 可通過ADC 采樣時間寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位 設置, ADC_SMPR2控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17 。每個通道可以分別用不同的時間采樣。其中采樣周期最小是1.5個,即 如果我們要達到最快的采樣,那么應該設置采樣周期為1.5個周期,這里 說的周期就是 1/ADC_CLK。
ADC 的總轉換時間跟ADC 的輸入時鐘和采樣時間有關,其公式如下:
(轉換時間) Tconv = 采樣時間 + 12.5個周期
其中Tconv為ADC總轉換時間,當ADC_CLK=14Mhz的時候,并設置1.5個周 期的采樣時間,則Tcovn=1.5+12.5=14個周期=1us。
(6)標號6:數據寄存器
ADC 轉換后的數據根據轉換組的不同,規(guī)則組的數據放在ADC_DR 寄 存器內,注入組的數據放在 JDRx內。 因為STM32F1的ADC是12位轉換精度,而數據寄存器是16位,所以ADC 在存放數據的時候就有左對齊和右對齊區(qū)分。如果是左對齊,AD轉換完 成數據存放在 ADC_DR 寄存器的[4:15]位內;如果是右對齊,則存放在 ADC_DR 寄存器的[0:11]位內。具體選擇何種存放方式,需通過ADC_CR2 的 11 位 ALIGN 設置。
(7)標號7:中斷
當發(fā)生如下事件且使能相應中斷標志位時,ADC能產生中斷。
1.轉換結束(規(guī)則轉換)與注入轉換結束
2.模擬看門狗事件
3.DMA請求
二、STM32F1 ADC配置步驟
(1)使能端口時鐘和ADC時鐘,設置引腳模式為模擬輸入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模擬輸入模式
(2)設置ADC的分頻因子
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
(3)初始化ADC參數,包括ADC工作模式、規(guī)則序列等
ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
(4)使能ADC并校準
ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADC_Cmd(ADC1, ENABLE);//開啟AD轉換器
執(zhí)行復位校準的方法是: ADC_ResetCalibration(ADC1);
執(zhí)行 ADC 校準的方法是: ADC_StartCalibration(ADC1); //開始指定 ADC1 的校準狀態(tài)
while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校準結束
while(ADC_GetCalibrationStatus(ADC1)); //等待校準結束
(5)讀取ADC轉換值 設置規(guī)則序列通道以及采樣周期的庫函數是:
ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 )
設置好規(guī)則序列通道及采樣周期,接下來就要開啟轉換,由于我們采 用的是軟件觸發(fā),庫函數
ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
要開啟 ADC轉換.
三、編寫ADC控制程序
本章所要實現(xiàn)的功能是:通過ADC1通道1采樣外部電壓值,將采樣的 AD值和轉換后的電壓值通過串口打印出來,同時D1指示燈閃爍,提示系 統(tǒng)正常運行。
程序框架如下: (1)初始化ADC1_IN1相關參數,開啟ADC1 (2)編寫獲取ADC1_IN1的AD轉換值函數 (3)編寫主函數
1 #ifndef _adc_H 2 #define _adc_H 3 4 #include "system.h" 5 6 void ADCx_Init(void); 7 u16 Get_ADC_Value(u8 ch,u8 times); 8 9 10 #endif
1 #include "adc.h"
2 #include "SysTick.h"
3
4 /*******************************************************************************
5 * 函 數 名 : ADCx_Init
6 * 函數功能 : ADC初始化
7 * 輸 入 : 無
8 * 輸 出 : 無
9 *******************************************************************************/
10 void ADCx_Init(void)
11 {
12 GPIO_InitTypeDef GPIO_InitStructure; //定義結構體變量
13 ADC_InitTypeDef ADC_InitStructure;
14
15 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
16
17 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//設置ADC分頻因子6 72M/6=12,ADC最大時間不能超過14M
18
19 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//ADC
20 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模擬輸入
21 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
22 GPIO_Init(GPIOA,&GPIO_InitStructure);
23
24 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
25 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非掃描模式
26 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//關閉連續(xù)轉換
27 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//禁止觸發(fā)檢測,使用軟件觸發(fā)
28 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右對齊
29 ADC_InitStructure.ADC_NbrOfChannel = 1;//1個轉換在規(guī)則序列中 也就是只轉換規(guī)則序列1
30 ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
31
32 ADC_Cmd(ADC1, ENABLE);//開啟AD轉換器
33
34 ADC_ResetCalibration(ADC1);//重置指定的ADC的校準寄存器
35 while(ADC_GetResetCalibrationStatus(ADC1));//獲取ADC重置校準寄存器的狀態(tài)
36
37 ADC_StartCalibration(ADC1);//開始指定ADC的校準狀態(tài)
38 while(ADC_GetCalibrationStatus(ADC1));//獲取指定ADC的校準程序
39
40 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或者失能指定的ADC的軟件轉換啟動功能
41 }
42
43 /*******************************************************************************
44 * 函 數 名 : Get_ADC_Value
45 * 函數功能 : 獲取通道ch的轉換值,取times次,然后平均
46 * 輸 入 : ch:通道編號
47 times:獲取次數
48 * 輸 出 : 通道ch的times次轉換結果平均值
49 *******************************************************************************/
50 u16 Get_ADC_Value(u8 ch,u8 times)
51 {
52 u32 temp_val=0;
53 u8 t;
54 //設置指定ADC的規(guī)則組通道,一個序列,采樣時間
55 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); //ADC1,ADC通道,239.5個周期,提高采樣時間可以提高精確度
56
57 for(t=0;t<times;t++)
58 {
59 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的ADC1的軟件轉換啟動功能
60 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束
61 temp_val+=ADC_GetConversionValue(ADC1);
62 delay_ms(5);
63 }
64 return temp_val/times;
65 }
1 #include "system.h"
2 #include "SysTick.h"
3 #include "led.h"
4 #include "usart.h"
5 #include "adc.h"
6
7
8 /*******************************************************************************
9 * 函 數 名 : main
10 * 函數功能 : 主函數
11 * 輸 入 : 無
12 * 輸 出 : 無
13 *******************************************************************************/
14 int main()
15 {
16 u8 i=0;
17 u16 value=0;
18 float vol;
19
20 SysTick_Init(72);
21 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中斷優(yōu)先級分組 分2組
22 LED_Init();
23 USART1_Init(9600);
24 ADCx_Init();
25
26 while(1)
27 {
28 i++;
29 if(i%20==0)
30 {
31 led1=!led1;
32 }
33
34 if(i%50==0)
35 {
36 value=Get_ADC_Value(ADC_Channel_1,20);
37 printf("檢測AD值為:%d
",value);
38 vol=(float)value*(3.3/4096);
39 printf("檢測電壓值為:%.2fV
",vol);
40 }
41 delay_ms(10);
42 }
43 }
總結
以上是生活随笔為你收集整理的(stm32f103学习总结)—ADC模数转换实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: din算法 代码_深度兴趣网络(DIN,
- 下一篇: 天眼查:一季度旅游行业新增注册企业14.