f401和f407,f401和f407的區別
1)實驗平臺:alientek 阿波羅 STM32F767 開發板
2)摘自《STM32F7 開發指南(HAL 庫版)》關注官方微信號公眾號,獲取更多資料:正點原子
第二十三章 ADC 實驗
本章我們將向大家介紹 STM32F4 的 ADC 功能。在本章中,我們將使用 STM32F4 的 ADC1
通道 5 來采樣外部電壓值,并在 TFTLCD 模塊上顯示出來。本章將分為如下幾個部分:
23.1 STM32F4 ADC 簡介
23.2 硬件設計
23.3 軟件設計
23.4 下載驗證
23.1 STM32F4 ADC 簡介
STM32F4xx 系列一般都有 3 個 ADC,這些 ADC 可以獨立使用,也可以使用雙重/三重模
式(提高采樣率)。STM32F4 的 ADC 是 12 位逐次逼近型的模擬數字轉換器。它有 19 個通道,
可測量 16 個外部源、2 個內部源和 Vbat 通道的信號。這些通道的 A/D 轉換可以單次、連續、
掃描或間斷模式執行。ADC 的結果可以左對齊或右對齊方式存儲在 16 位數據寄存器中。 模擬
看門狗特性允許應用程序檢測輸入電壓是否超出用戶定義的高/低閥值。
STM32F407ZGT6 包含有 3 個 ADC。STM32F4 的 ADC 最大的轉換速率為 2.4Mhz,也就是
轉換時間為 0.41us(在 ADCCLK=36M,采樣周期為 3 個 ADC 時鐘下得到),不要讓 ADC 的時
鐘超過 36M,否則將導致結果準確度下降。
STM32F4 將 ADC 的轉換分為 2 個通道組:規則通道組和注入通道組。規則通道相當于你
正常運行的程序,而注入通道呢,就相當于中斷。在你程序正常執行的時候,中斷是可以打斷
你的執行的。同這個類似,注入通道的轉換可以打斷規則通道的轉換, 在注入通道被轉換完成
之后,規則通道才得以繼續轉換。
通過一個形象的例子可以說明:假如你在家里的院子內放了 5 個溫度探頭,室內放了 3 個
溫度探頭;你需要時刻監視室外溫度即可,但偶爾你想看看室內的溫度;因此你可以使用規則
通道組循環掃描室外的 5 個探頭并顯示 AD 轉換結果,當你想看室內溫度時,通過一個按鈕啟
動注入轉換組(3 個室內探頭)并暫時顯示室內溫度,當你放開這個按鈕后,系統又會回到規則通
道組繼續檢測室外溫度。從系統設計上,測量并顯示室內溫度的過程中斷了測量并顯示室外溫
度的過程,但程序設計上可以在初始化階段分別設置好不同的轉換組,系統運行中不必再變更
循環轉換的配置,從而達到兩個任務互不干擾和快速切換的結果。可以設想一下,如果沒有規
則組和注入組的劃分,當你按下按鈕后,需要從新配置 AD 循環掃描的通道,然后在釋放按鈕
后需再次配置 AD 循環掃描的通道。
上面的例子因為速度較慢,不能完全體現這樣區分(規則通道組和注入通道組)的好處,但
在工業應用領域中有很多檢測和監視探頭需要較快地處理,這樣對 AD 轉換的分組將簡化事件
處理的程序并提高事件處理的速度。
STM32F4 其 ADC 的規則通道組最多包含 16 個轉換,而注入通道組最多包含 4 個通道。關
于這兩個通道組的詳細介紹,請參考《STM32F4xx 中文參考手冊》第 250 頁,第 11.3.3 節。
STM32F4 的 ADC 可以進行很多種不同的轉換模式,這些模式在《STM32F4xx 中文參考手
冊》的第 11 章也都有詳細介紹,我們這里就不在一一列舉了。我們本章僅介紹如何使用規則通
道的單次轉換模式。
STM32F4 的 ADC 在單次轉換模式下,只執行一次轉換,該模式可以通過 ADC_CR2 寄存
器的 ADON 位(只適用于規則通道)啟動,也可以通過外部觸發啟動(適用于規則通道和注入
通道),這時 CONT 位為 0。
以規則通道為例,一旦所選擇的通道轉換完成,轉換結果將被存在 ADC_DR 寄存器中,
EOC(轉換結束)標志將被置位,如果設置了 EOCIE,則會產生中斷。然后 ADC 將停止,直
到下次啟動。
接下來,我們介紹一下我們執行規則通道的單次轉換,需要用到的 ADC 寄存器。第一個
要介紹的是 ADC 控制寄存器(ADC_CR1 和 ADC_CR2)。ADC_CR1 的各位描述如圖 23.1.1 所
示:
圖 23.1.1 ADC_CR1 寄存器各位描述
這里我們不再詳細介紹每個位,而是抽出幾個我們本章要用到的位進行針對性的介紹,詳
細的說明及介紹,請參考《STM32F4xx 中文參考手冊》第 11.13.2 節。
ADC_CR1 的 SCAN 位,該位用于設置掃描模式,由軟件設置和清除,如果設置為 1,則
使用掃描模式,如果為 0,則關閉掃描模式。在掃描模式下,由 ADC_SQRx 或 ADC_JSQRx 寄
存器選中的通道被轉換。如果設置了 EOCIE 或 JEOCIE,只在最后一個通道轉換完畢后才會產
生 EOC 或 JEOC 中斷。
ADC_CR1[25:24]用于設置 ADC 的分辨率,詳細的對應關系如圖 23.1.2 所示:
圖 23.1.2 ADC 分辨率選擇
本章我們使用 12 位分辨率,所以設置這兩個位為 0 就可以了。接著我們介紹 ADC_CR2,
該寄存器的各位描述如圖 23.1.3 所示:
圖 23.1.3 ADC_CR2 寄存器各位描述
該寄存器我們也只針對性的介紹一些位:ADON 位用于開關 AD 轉換器。而 CONT 位用于
設置是否進行連續轉換,我們使用單次轉換,所以 CONT 位必須為 0。ALIGN 用于設置數據對
齊,我們使用右對齊,該位設置為 0。
EXTEN[1:0]用于規則通道的外部觸發使能設置,詳細的設置關系如圖 23.1.4 所示:
圖 23.1.4 ADC 規則通道外部觸發使能設置
我們這里使用的是軟件觸發,即不使用外部觸發,所以設置這 2 個位為 0 即可。ADC_CR2
的 SWSTART 位用于開始規則通道的轉換,我們每次轉換(單次轉換模式下)都需要向該位寫
1。
第二個要介紹的是 ADC 通用控制寄存器(ADC_CCR),該寄存器各位描述如圖 23.1.5 所
示:
圖 23.1.5 ADC_CCR 寄存器各位描述
該寄存器我們也只針對性的介紹一些位:TSVREFE 位是內部溫度傳感器和 Vrefint 通道使
能位,內部溫度傳感器我們將在下一章介紹,這里我們直接設置為 0。ADCPRE[1:0]用于設置
ADC 輸入時鐘分頻,00~11 分別對應 2/4/6/8 分頻,STM32F4 的 ADC 最大工作頻率是 36Mhz,
而 ADC時鐘(ADCCLK)來自 APB2,APB2頻率一般是 84Mhz,所以我們一般設置 ADCPRE=01,
即 4 分頻,這樣得到 ADCCLK 頻率為 21Mhz。MULTI[4:0]用于多重 ADC 模式選擇,詳細的設
置關系如圖 23.1.6 所示:
圖 23.1.6 多重 ADC 模式選擇設置
本章我們僅用了 ADC1(獨立模式),并沒用到多重 ADC 模式,所以設置這 5 個位為 0 即
可。
第三個要介紹的是 ADC 采樣時間寄存器(ADC_SMPR1 和 ADC_SMPR2),這兩個寄存器
用于設置通道 0~18 的采樣時間,每個通道占用 3 個位。ADC_SMPR1 的各位描述如圖 23.1.7
所示:
圖 23.1.7 ADC_SMPR1 寄存器各位描述
ADC_SMPR2 的各位描述如下圖 23.1.8 所示:
圖 23.1.8 ADC_SMPR2 寄存器各位描述
對于每個要轉換的通道,采樣時間建議盡量長一點,以獲得較高的準確度,但是這樣會降
低 ADC 的轉換速率。ADC 的轉換時間可以由以下公式計算:
Tcovn=采樣時間+12 個周期
其中:Tcovn 為總轉換時間,采樣時間是根據每個通道的 SMP 位的設置來決定的。例如,
當 ADCCLK=21Mhz 的時候,并設置 3 個周期的采樣時間,則得到:Tcovn=3+12=15 個周期
=0.71us。
第四個要介紹的是 ADC 規則序列寄存器(ADC_SQR1~3),該寄存器總共有 3 個,這幾個
寄存器的功能都差不多,這里我們僅介紹一下 ADC_SQR1,該寄存器的各位描述如圖 23.1.9 所
示:
圖 23.1.9 ADC_ SQR1 寄存器各位描述
L[3:0]用于存儲規則序列的長度,我們這里只用了 1 個,所以設置這幾個位的值為 0。其
他的 SQ13~16 則存儲了規則序列中第 13~16 個通道的編號(0~18)。另外兩個規則序列寄存器
同 ADC_SQR1 大同小異,我們這里就不再介紹了,要說明一點的是:我們選擇的是單次轉換,
所以只有一個通道在規則序列里面,這個序列就是 SQ1,至于 SQ1 里面哪個通道,完全由用戶
自己設置,通過 ADC_SQR3 的最低 5 位(也就是 SQ1)設置。
第五個要介紹的是 ADC 規則數據寄存器(ADC_DR)。規則序列中的 AD 轉化結果都將被存
在這個寄存器里面,而注入通道的轉換結果被保存在 ADC_JDRx 里面。ADC_DR 的各位描述
如圖 23.1.10:
圖 23.1.10 ADC_ JDRx 寄存器各位描述
這里要提醒一點的是,該寄存器的數據可以通過 ADC_CR2 的 ALIGN 位設置左對齊還是
右對齊。在讀取數據的時候要注意。
最后一個要介紹的 ADC 寄存器為 ADC 狀態寄存器(ADC_SR),該寄存器保存了 ADC 轉
換時的各種狀態。該寄存器的各位描述如圖 23.1.11 所示:
圖 23.1.11 ADC_ SR 寄存器各位描述
這里我們僅介紹將要用到的是 EOC 位,我們通過判斷該位來決定是否此次規則通道的 AD
轉換已經完成,如果該位位 1,則表示轉換完成了,就可以從 ADC_DR 中讀取轉換結果,否則
等待轉換完成。
至此,本章要用到的 ADC 相關寄存器全部介紹完畢了,對于未介紹的部分,請大家參考
《STM32F4xx 中文參考手冊》第 11 章相關章節。通過以上介紹,我們了解了 STM32F4 的單次
轉換模式下的相關設置,接下來我們介紹使用庫函數來設置 ADC1 的通道 5 來進行 AD 轉換的
步驟,這里需要說明一下,使用到的庫函數分布在 stm32f4xx_adc.c 文件和 stm32f4xx_adc.h 文
件中。下面講解其詳細設置步驟:
1)開啟 PA 口時鐘和 ADC1 時鐘,設置 PA5 為模擬輸入。
STM32F407ZGT6 的 ADC1 通道 5 在 PA5 上,所以,我們先要使能 GPIOA 的時鐘,然后
設置 PA5 為模擬輸入。同時我們要把 PA5 復用為 ADC,所以我們要使能 ADC1 時鐘。
這里特別要提醒,對于 IO 口復用為 ADC 我們要設置模式為模擬輸入,而不是復用功能,
也不需要調用 GPIO_PinAFConfig 函數來設置引腳映射關系。
使能 GPIOA 時鐘和 ADC1 時鐘都很簡單,具體方法為:
這里需要說明一下,ADC 的通道與引腳的對應關系在 STM32F4 的數據手冊可以查到,我
們這里使用 ADC1 的通道 5,在數據手冊中的表格為:
表 23.1.12 ADC1 通道 5 對應引腳查看表
這里我們把 ADC1~ADC3 的引腳與通道對應關系列出來, 16 個外部源的對應關系如下表:
表 23.1.13 ADC1~ADC3 引腳對應關系表
2)初始化 ADC,設置 ADC 時鐘分頻系數,分辨率,模式,掃描方式,對齊方式等信息。
在 HAL 庫中,初始化 ADC 是通過函數 HAL_ADC_Init 來實現的,該函數聲明為:
該結構體定義和其他外設比較類似,我們著重看第二個成員變量 Init 含義,它是結構體
ADC_InitTypeDef 類型,結構體 ADC_InitTypeDef 定義為:
我們直接把每個成員變量含義注釋在結構體定義的后面,請大家仔細閱讀上面注釋。
這里我們需要說明一下,和其他外設一樣,HAL 庫同樣提供了 ADC 的 MSP 初始化函數,
一般情況下,時鐘使能和 GPIO 初始化都會放在 MSP 初始化函數中。函數聲明為:
4)開啟 AD 轉換器。
在設置完了以上信息后,我們就開啟 AD 轉換器了(通過 ADC_CR2 寄存器控制)。
HAL_ADC_Start(&ADC1_Handler); //開啟 ADC
5)配置通道,讀取通道 ADC 值。
在上面的步驟完成后,ADC 就算準備好了。接下來我們要做的就是設置規則序列 1 里面的
通道,然后啟動 ADC 轉換。在轉換結束后,讀取轉換結果值值就是了。
設置規則序列通道以及采樣周期的函數是:
該函數有兩個入口參數,第一個就不用多說了,接下來我們看第二個入口參數 sConfig,它
是 ADC_ChannelConfTypeDef 結構體指針類型,結構體定義如下:
該結構體有四個成員變量,對于 STM32F4 只用到前面三個。Channel 用來設置 ADC 通道,
Rank 用來設置要配置的通道是規則序列中的第幾個轉換,SamplingTime 用來設置采樣時間。
使用實例為:
配置好通道并且使能 ADC 后,接下來就是讀取 ADC 值。這里我們采取的是查詢方式讀取,
所以我們還要等待上一次轉換結束。此過程 HAL 庫 提 供 了 專 用 函 數
等待上一次轉換結束之后,接下來就是讀取 ADC 值,函數為:
這兩個函數的使用方法都比較簡單,這里我們就不累贅了。
這里還需要說明一下ADC的參考電壓,探索者STM32F4開發板使用的是STM32F407ZGT6,
該芯片只有 Vref+參考電壓引腳,Vref+的輸入范圍為:1.8~VDDA。探索者 STM32F4 開發板通
過 P7 端口,來設置 Vref+的參考電壓,默認的我們是通過跳線帽將 ref+接到 VDDA,參考電壓
就是 3.3V。如果大家想自己設置其他參考電壓,將你的參考電壓接在 Vref+上就 OK 了(注意
要共地)。另外,對于還有 Vref-引腳的 STM32F4 芯片,直接就近將 Vref-接 VSSA 就可以了。
本章我們的參考電壓設置的是 3.3V。
通過以上幾個步驟的設置,我們就能正常的使用 STM32F4 的 ADC1 來執行 AD 轉換操作
了。
23.2 硬件設計
本實驗用到的硬件資源有:
1) 指示燈 DS0
2) TFTLCD 模塊
3) ADC
4) 杜邦線
前面 2 個均已介紹過,而 ADC 屬于 STM32F4 內部資源,實際上我們只需要軟件設置就可
以正常工作,不過我們需要在外部連接其端口到被測電壓上面。本章,我們通過 ADC1 的通道
5(PA5)來讀取外部電壓值,探索者 STM32F4 開發板沒有設計參考電壓源在上面,但是板上
有幾個可以提供測試的地方:1,3.3V 電源。2,GND。3,后備電池。注意:這里不能接到板
上 5V 電源上去測試,這可能會燒壞 ADC!。
因為要連接到其他地方測試電壓,所以我們需要 1 跟杜邦線,或者自備的連接線也可以,
一頭插在多功能端口 P12 的 ADC 插針上(與 PA5 連接),另外一頭就接你要測試的電壓點(確
保該電壓不大于 3.3V 即可)。
23.3 軟件設計
打開實驗工程可以發現,我們在 FWLIB 分組下面新增了 stm32f4xx_hal_adc.c 源文件,同
時會引入對應的頭文件 stm32f4xx_hal_adc.h。ADC 相關的庫函數和宏定義都分布在這兩個文件
中。同時,我們在 HARDWARE 分組下面新建了 adc.c,也引入了對應的頭文件 adc.h。這兩個
文件是我們編寫的 adc 相關的初始化函數和操作函數。
打開 adc.c,代碼如下:
此部分代碼就 3 個函數,Adc_Init 函數用于初始化 ADC1。這里基本上是按我們上面的步
驟來初始化的,我們用標號①~④標示出來步驟。這里我們僅開通了 1 個通道,即通道 5。第二
個函數 Get_Adc,用于讀取某個通道的 ADC 值,例如我們讀取通道 5 上的 ADC 值,就可以通
過 Get_Adc(ADC_Channel_5)得到。最后一個函數 Get_Adc_Average,用于多次獲取 ADC 值,
取平均,用來提高準確度。
頭文件 adc.h 代碼比較簡單,主要是三個函數申明。接下來我們看看 main 函數內容:
此部分代碼,我們在 TFTLCD 模塊上顯示一些提示信息后,將每隔 250ms 讀取一次 ADC
通道 5 的值,并顯示讀到的 ADC 值(數字量),以及其轉換成模擬量后的電壓值。同時控制 LED0
閃爍,以提示程序正在運行。這里關于最后的 ADC 值的顯示我們說明一下,首先我們在液晶
固定位置顯示了小數點,然后后面計算步驟中,先計算出整數部分在小數點前面顯示,然后計
算出小數部分,在小數點后面顯示。這樣就在液晶上面顯示轉換結果的整數和小數部分。
23.4 下載驗證
在代碼編譯成功之后,我們通過下載代碼到 ALIENTEK 探索者 STM32F4 開發板上,可以
看到 LCD 顯示如圖 23.4.1 所示:
圖 23.4.1 ADC 實驗測試圖
上圖中,我們是將 ADC 和 TPAD 連接在一起,可以看到 TPAD 信號電平為 3V 左右,這是
因為存在上拉電阻 R64 的緣故。
同時伴隨 DS0 的不停閃爍,提示程序在運行。大家可以試試把杜邦線接到其他地方,看看
電壓值是否準確?但是一定別接到 5V 上面去,否則可能燒壞 ADC!
特別注意:STM32F4 的 ADC 精度貌似不怎么好,ADC 引腳直接接 GND,都可以讀到十
幾的數值,相比 STM32F103 來說,要差了一些,在使用的時候,請大家注意下這個問題。
通過這一章的學習,我們了解了 STM32F4 ADC 的使用,但這僅僅是 STM32F4 強大的 ADC
功能的一小點應用。STM32F4 的 ADC 在很多地方都可以用到,其 ADC 的 DMA 功能是很不錯
的,建議有興趣的大家深入研究下 STM32F4 的 ADC,相信會給你以后的開發帶來方便。