本章參考資料:《STM32F4xx 中文參考手冊》ADC章節。
1 、ADC 簡介
STM32F429IGT6 有 3 個 ADC,每個 ADC有 12 位、10 位、8 位和 6 位可選,每個ADC有 16 個外部通道。另外還有兩個內部 ADC源和 V BAT 通道掛在 ADC1 上。ADC具有獨立模式、雙重模式和三重模式,對於不同 AD 轉換要求幾乎都有合適的模式可選。ADC功能非常強大,具體的我們在功能框圖中分析每個部分的功能。
2 、ADC功能框圖剖析
單個ADC功能框圖如下所示:
掌握了 ADC的功能框圖,就可以對 ADC有一個整體的把握,在編程的時候可以做到了然如胸,不會一知半解。框圖講解采用從左到右的方式,跟 ADC 采集數據,轉換數據,傳輸數據的方向大概一致。
①電壓輸入范圍
ADC輸入范圍為:V REF- ≤ V IN ≤ V REF+ 。由 V REF- 、V REF+ 、V DDA 、V SSA 、這四個外部引腳決定。
我們在設計原理圖的時候一般把 V SSA 和 V REF- 接地,把 V REF+ 和 V DDA 接 3V3,得到ADC的輸入電壓范圍為:0~3.3V。
如果我們想讓輸入的電壓范圍變寬,去到可以測試負電壓或者更高的正電壓,我們可以在外部加一個電壓調理電路,把需要轉換的電壓抬升或者降壓到 0~3.3V,這樣 ADC就可以測量了。
若測量的電壓超過0~3.3V,一個簡單的處理辦法為:處理后電壓的輸入范圍為(-10V~10V)
②輸入通道
我們確定好 ADC輸入電壓之后,那么電壓怎么輸入到 ADC?這里我們引入通道的概念,STM32 的 ADC多達 19個通道,其中外部的 16個通道就是框圖中的 ADCx_IN0、ADCx_IN1...ADCx_IN5。這 16 個通道對應着不同的 IO 口,具體是哪一個 IO 口可以從手冊查詢到。其中 ADC1/2/3 還有內部通道: ADC1的通道 ADC1_IN16 連接到內部的 VSS,通道 ADC1_IN17 連接到了內部參考電壓 V REFINT 連接,通道 ADC1_IN18 連接到了芯片內部的溫度傳感器或者備用電源 V BAT 。ADC2 和 ADC3 的通道 16、17、18 全部連接到了內部的 VSS。
外部的 16個通道在轉換的時候又分為規則通道和注入通道,其中規則通道最多有 16路,注入通道最多有 4 路。那這兩個通道有什么區別?在什么時候使用?
規則通道
規則通道:顧名思意,規則通道就是很規矩的意思,我們平時一般使用的就是這個通道,或者應該說我們用到的都是這個通道,沒有什么特別要注意的可講。
注入通道
注入,可以理解為插入,插隊的意思,是一種不安分的通道。它是一種在規則通道轉換的時候強行插入要轉換的一種。如果在規則通道轉換過程中,有注入通道插隊,那么就要先轉換完注入通道,等注入通道轉換完成后,再回到規則通道的轉換流程。這點跟中斷程序很像,都是不安分的主。所以,注入通道只有在規則通道存在時才會出現。
③轉換順序
規則序列
規則序列寄存器有 3個,分別為 SQR3、SQR2、SQR1。SQR3 控制着規則序列中的第一個到第六個轉換,對應的位為:SQ1[4:0]~SQ6[4:0],第一次轉換的是位 4:0 SQ1[4:0],如果通道 16想第一次轉換,那么在 SQ1[4:0]寫 16 即可。SQR2 控制着規則序列中的第 7 到第12 個轉換,對應的位為:SQ7[4:0]~SQ12[4:0],如果通道 1 想第 8 個轉換,則 SQ8[4:0]寫 1即可。SQR1 控制着規則序列中的第 13 到第 16 個轉換,對應位為:SQ13[4:0]~SQ16[4:0],如果通道 6想第 10 個轉換,則 SQ10[4:0]寫 6 即可。具體使用多少個通道,由 SQR1 的位L[3:0]決定,最多 16 個通道。
注入序列
注入序列寄存器 JSQR只有一個,最多支持 4 個通道,具體多少個由 JSQR的 JL[2:0]決定。如果 JL的 值小於 4的話,則 JSQR 跟 SQR決定轉換順序的設置不一樣,第一次轉換的不是 JSQR1[4:0],而是 JCQRx[4:0] ,x = (4-JL),跟 SQR剛好相反。如果 JL=00(1個轉換),那么轉換的順序是從 JSQR4[4:0]開始,而不是從 JSQR1[4:0]開始,這個要注意,編程的時候不要搞錯。當 JL等於 4時,跟 SQR一樣。
④觸發源
通道選好了,轉換的順序也設置好了,那接下來就該開始轉換了。ADC轉換可以由ADC控制寄存器 2: ADC_CR2 的 ADON 這個位來控制,寫 1 的時候開始轉換,寫 0 的時候停止轉換,這個是最簡單也是最好理解的開啟 ADC轉換的控制方式,理解起來沒啥技術含量。
除了這種庶民式的控制方法,ADC還支持外部事件觸發轉換,這個觸發包括內部定時器觸發和外部 IO 觸發。觸發源有很多,具體選擇哪一種觸發源,由 ADC 控制寄存器2:ADC_CR2 的 EXTSEL[2:0]和 JEXTSEL[2:0]位來控制。EXTSEL[2:0]用於選擇規則通道的觸發源,JEXTSEL[2:0]用於選擇注入通道的觸發源。選定好觸發源之后,觸發源是否要激活,則由 ADC控制寄存器 2:ADC_CR2 的 EXTTRIG 和 JEXTTRIG 這兩位來激活。
如果使能了外部觸發事件,我們還可以通過設置 ADC控制寄存器 2:ADC_CR2 的EXTEN[1:0]和 JEXTEN[1:0]來控制觸發極性,可以有 4 種狀態,分別是:禁止觸發檢測、上升沿檢測、下降沿檢測以及上升沿和下降沿均檢測。
⑤轉換時間
ADC 時鍾
ADC輸入時鍾 ADC_CLK 由 PCLK2 經過分頻產生,最大值是 36MHz,典型值為30MHz,分頻因子由 ADC通用控制寄存器 ADC_CCR的 ADCPRE[1:0]設置,可設置的分頻系數有 2、4、6和 8,注意這里沒有 1 分頻。對於 STM32F429IGT6 我們一般設置
PCLK2=HCLK/2=90MHz。所以程序一般使用 4 分頻或者 6 分頻。
采樣時間
ADC需要若干個 ADC_CLK 周期完成對輸入的電壓進行采樣,采樣的周期數可通過ADC 采樣時間寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位設置,ADC_SMPR2控制的是通道 0~9,ADC_SMPR1 控制的是通道 10~17。每個通道可以分別用不同的時間采樣。其中采樣周期最小是 3 個,即如果我們要達到最快的采樣,那么應該設置采樣周期為 3 個周期,這里說的周期就是 1/ADC_CLK。
ADC的總轉換時間跟 ADC 的輸入時鍾和采樣時間有關,公式為:
Tconv = 采樣時間 + 12 個周期
當 ADCCLK = 30MHz,即 PCLK2 為 60MHz,ADC時鍾為 2 分頻,采樣時間設置為 3個周期,那么總的轉換時為:Tconv = 3 + 12 = 15 個周期 =0.5us。
一般我們設置 PCLK2=90MHz,經過 ADC預分頻器能分頻到最大的時鍾只能是 22.5M,采樣周期設置為 3 個周期,算出最短的轉換時間為 0.6667us,這個才是最常用的。
⑥數據寄存器
一切准備就緒后,ADC轉換后的數據根據轉換組的不同,規則組的數據放在ADC_DR 寄存器,注入組的數據放在 JDRx。如果是使用雙重或者三重模式那規矩組的數據是存放在通用規矩寄存器 ADC_CDR 內的。
規則數據寄存器 ADC_DR
ADC規則組數據寄存器 ADC_DR只有一個,是一個 32 位的寄存器,只有低 16位有效並且只是用於獨立模式存放轉換完成數據。因為 ADC的最大精度是 12 位,ADC_DR是16 位有效,這樣允許 ADC存放數據時候選擇左對齊或者右對齊,具體是以哪一種方式存放,由 ADC_CR2 的 11位 ALIGN 設置。假如設置 ADC精度為 12 位,如果設置數據為左對齊,那 AD 轉換完成數據存放在 ADC_DR 寄存器的[4:15]位內;如果為右對齊,則存放在 ADC_DR寄存器的[0:11]位內。
規則通道可以有 16個這么多,可規則數據寄存器只有一個,如果使用多通道轉換,那轉換的數據就全部都擠在了 DR里面,前一個時間點轉換的通道數據,就會被下一個時間點的另外一個通道轉換的數據覆蓋掉,所以當通道轉換完成后就應該把數據取走,或者開啟 DMA模式,把數據傳輸到內存里面,不然就會造成數據的覆蓋。最常用的做法就是開啟 DMA傳輸。
如果沒有使用 DMA傳輸,我們一般都需要使用 ADC狀態寄存器 ADC_SR獲取當前ADC轉換的進度狀態,進而進行程序控制。
注入數據寄存器 ADC_JDRx
ADC注入組最多有 4 個通道,剛好注入數據寄存器也有 4 個,每個通道對應着自己的寄存器,不會跟規則寄存器那樣產生數據覆蓋的問題。ADC_JDRx 是 32位的,低 16 位有效,高 16位保留,數據同樣分為左對齊和右對齊,具體是以哪一種方式存放,由ADC_CR2 的 11 位 ALIGN 設置。
通用規則數據寄存器 ADC_CDR
規則數據寄存器 ADC_DR 是僅適用於獨立模式的,而通用規則數據寄存器 ADC_CDR是適用於雙重和三重模式的。獨立模式就是僅僅適用三個 ADC的其中一個,雙重模式就是同時使用 ADC1和 ADC2,而三重模式就是三個 ADC同時使用。在雙重或者三重模式下一般需要配合 DMA數據傳輸使用。
⑦中斷
1. 轉換結束中斷
數據轉換結束后,可以產生中斷,中斷分為四種:規則通道轉換結束中斷,注入轉換通道轉換結束中斷,模擬看門狗中斷和溢出中斷。其中轉換結束中斷很好理解,跟我們平時接觸的中斷一樣,有相應的中斷標志位和中斷使能位,我們還可以根據中斷類型寫相應配套的中斷服務程序。
2. 模擬看門狗中斷
當被 ADC轉換的模擬電壓低於低閾值或者高於高閾值時,就會產生中斷,前提是我們開啟了模擬看門狗中斷,其中低閾值和高閾值由 ADC_LTR和 ADC_HTR 設置。例如我們設置高閾值是 2.5V,那么模擬電壓超過 2.5V的時候,就會產生模擬看門狗中斷,反之低閾值也一樣。
3.溢出中斷
如果發生 DMA傳輸數據丟失,會置位 ADC狀態寄存器 ADC_SR 的 OVR位,如果同時使能了溢出中斷,那在轉換結束后會產生一個溢出中斷。
4.DMA 請求
規則和注入通道轉換結束后,除了產生中斷外,還可以產生 DMA請求,把轉換好的數據直接存儲在內存里面。對於獨立模式的多通道 AD 轉換使用 DMA 傳輸非常有必要,程序編程簡化了很多。對於雙重或三重模式使用 DMA傳輸幾乎可以說是必要的。有關DMA請求需要配合《STM32F4xx 中文參考手冊》DMA控制器這一章節來學習。一般我們在使用 ADC的時候都會開啟 DMA傳輸。
⑧電壓轉換
模擬電壓經過 ADC轉換后,是一個相對精度的數字值,如果通過串口以 16 進制打印出來的話,可讀性比較差,那么有時候我們就需要把數字電壓轉換成模擬電壓,也可以跟實際的模擬電壓(用萬用表測)對比,看看轉換是否准確。
我們一般在設計原理圖的時候會把 ADC的輸入電壓范圍設定在:0~3.3v,如果設置ADC 為 12 位的,那么 12 位滿量程對應的就是 3.3V,12 位滿量程對應的數字值是:2^12。數值 0 對應的就是 0V。如果轉換后的數值為 X ,X對應的模擬電壓為 Y,那么會有這么一個等式成立: 2^12 / 3.3 = X / Y,=> Y = (3.3 * X ) / 2^12。
3、 ADC 初始化結構體詳解
標准庫函數對每個外設都建立了一個初始化結構體 xxx_InitTypeDef(xxx 為外設名稱),結構體成員用於設置外設工作參數,並由標准庫函數 xxx_Init()調用這些設定參數進入設置外設相應的寄存器,達到配置外設工作環境的目的。
結構體 xxx_InitTypeDef和庫函數 xxx_Init 配合使用是標准庫精髓所在,理解了結構體xxx_InitTypeDef每個成員意義基本上就可以對該外設運用自如了。結構體 xxx_InitTypeDef定義在 stm32f4xx_xxx.h文件中,庫函數 xxx_Init 定義在 stm32f4xx_xxx.c文件中,編程時我們可以結合這兩個文件內注釋使用。