一、ADC簡介
ADC模擬-數字轉換器
ADC可以將引腳連續變化的模擬電壓轉換為內存中存儲的數字變量,建立模擬電路到數字電路的橋梁
12位逐次逼近型ADC,1us轉換時間
輸入電壓范圍: 0~3.3V,轉換結果范圍:0~4095
18個輸入通道,可測量16個外部和2個內部信號源
規則組和注入組兩個轉換單元
模擬看門狗自動檢測輸入電壓范圍
STM32F2103C8T6? ADC資源:ADC1、ADC2、10個外部輸入通道
二、逐次逼近型ADC
逐次逼近型ADC內部結構
ADC0809:是一個獨立的8位逐次逼近型ADC芯片,在以前的時候,單片機的性能還不是很強,所以需要外掛一個ADC芯片才能進行AD轉換,這個ADC0809就是一款比較經典的ADC芯片,但現在單片機的性能和集成度都有很大的提升,很多單片機內部就已經集成了ADC外設,這樣就不用外掛芯片了,引腳可以直接測電壓,使用還是非常方便的
結構的分析
首先在最左邊這里IN0~IN7,是8路輸入通道,通過通道選擇開關,選中一路,輸入到比較器前面的箭頭的位置進行轉換
其次下面的這里是地址鎖存器和譯碼:就是你想選擇哪個通道,就把通道號放在這三個腳上,然后給一個鎖存信號,上面這里對應的通道開關就可以自動撥好了
上面這兩個部分就可以看作是一個可以通過模擬信號的數據選擇器
因為ADC轉換是一個很快的過程,你給一個開始信號,過個us就轉換完成了,所以說如果想轉換多路信號,那不必設計多個AD轉換器,只需要一個AD轉換器,然后加一個多路選擇開關,想轉換哪一路,就先撥一下開關,選中對應通道,然后在開始轉換就行了
這就是輸入通道選擇的部分,這個ADC0809只有8個輸入通道,我們STM32內部的ADC是有18個輸入通道的,所以對應這里,就是一個18路輸入的多路開關,然后輸入信號我們選擇好了,我們來看下一部分
怎么才能知道這個電壓對應的編碼數據是多少呢
這個就需要我們用逐次逼近的方法來一一比較了,首先一個電壓比較器,它可以判斷兩個輸入信號電壓的大小關系,輸出一個高低電平指示誰大誰小,它的兩個輸入端,一個待測的電壓,另一個這里DAC的電壓輸出端,DAC是數模轉換器(給他一個數據,他就可以輸出數據對應的電壓,DAC內部是使用加權電阻網絡來實現的轉換,想要深入探究看江科大51單片機教程里的DA/AD一節)
現在我們有了一個外部通道輸入的未知編碼的電壓和一個DAC輸出的已知編碼的電壓,它們同時輸入到電壓比較器,進行大小判斷,如果ADC輸出的電壓比較大,我就調小DAC數據,如果DAC輸出的電壓比較小,我就增大DAC數據,直到DAC輸出的電壓和外部通道輸入的電壓近似相等,這樣DAC輸入的數據就是外部電壓的編碼數據,這就是DAC的實現原理。這個電壓調節的過程就是這個逐次逼近SAR來完成的,為了最快找到未知電壓的編碼,通常我們會使用二分法進行尋找
例如:這里是8位的ADC,那編碼就是從0~255,那第一次比較的時候,我們就給DAC輸入255的一半,進行比較,就是128,然后看看誰大誰小,如果DAC電壓大了,如果第二次比較的時候,在就給128的一半,64,如果還是大,第三次比較的時候就給32,如果這次DAC電壓小了,那第四次就給32到64中間的值,然后繼續,這樣依次進行下去,就能最快地找到未知電壓的編碼
那然后AD轉化結束后,DAC的輸入數據就是未知電壓的編碼,輸出8位就有8根線,12位就有12根線
最上面EOC是轉換結束信號
START是開始轉換,給一個輸入脈沖,開始轉換
CLOCK是ADC時鐘,因為ADC內部是一步一步進行判斷的,所以需要時鐘來推動這個過程
下面的B\VREF+和VREF-是DAC的參考電壓,比如你給一個數據255,就是對應5V還是3.3V,就由這個參考電壓決定,這個DAC的參考電壓也決定了ADC的輸入范圍,所以它也是ADC參考電壓,最后左邊是整個芯片電路的供電,VCC和GND,通常這個參考電壓的正極和VCC是一樣的會接在一起,參考電壓的負極和GND也是一樣的,也連接在一起,所以一般情況下,ADC輸入電壓的范圍就和ADC的供電是一樣的
STM32F103C8T6內部的ADC結構
這里左邊是ADC的輸入通道,包括16個GPIO口,IN0~IN15,和兩個內部的通道,一個內部溫度傳感器,一個是VREFINT內部參考電壓,然后18個輸入通道,然后是一個模擬多路開關,可以指定我們想要選擇的通道,右邊是多路開關的輸出,進入到模數轉換器,這里模數轉換器就是執行的我們剛才講過的逐次比較的過程,轉換的結果會直接放在這個數據寄存器里,我們讀取寄存器就能知道ADC轉換的結果了
在模擬多路開關中,對于普通的ADC,多路開關一般都是只選一個的,就是選中某一個通道,開始轉換,等待轉換完成,取出結果,這是普通的流程
但是這里比較高級,他可以同時選中多個,而且在轉換的時候,還分成了兩個組,規則通道組和注入通道組,其中規則組可以一次性最多選中16個通道,注入組最多選中4個通道
在這里這個東西有什么作用呢
舉個簡單的例子
這就像你去餐廳點菜,普通的ADC是你指定一個菜,老板給你做,然后做好了送給你。但在這里是你指定一個菜單,這個菜單最多可以填16個菜,然后你直接遞個菜單給老板,老板按照菜單的順序依次做好,一次性給你端上來,這樣的話就可以大大提高效率,當然你的菜單也可以只寫一道菜,這樣這個菜單就簡化成了普通的模式了
對于這個菜單呢也有兩種,一種是規則組菜單,可以同時上16個菜,但是有一點,這個規則通道數據寄存器是有一個,也就是說這個桌子比較小,最多只能放一個菜,如果上16個菜,那不好意思,前15個菜都會被擠掉,你只能得到16個菜,所以對于規則組轉換來說,如果使用這個菜單的話,最好配合DMA來實現,DMA是一個數據轉運小幫手,它可以在每上一個菜之后把這兒菜挪到其他地方去,放置被覆蓋
注入組:這個注入組就比較高級了,它相當于餐廳的VIP座位,在這個座位上,一次性最多可以點4個菜,并且這里數據寄存器有4個,是可以同時上4個菜的,對于注入組而言,就不用擔心數據覆蓋的問題了,一般情況下我們使用規則組就完全足夠了
首先,左下角這里就是觸發轉換的部分,也就是最上面的START信號,開始轉換,對于STM32的ADC,觸發ADC開始轉換的信號有兩種,一種是軟件觸發,就是你在程序中手動調用一條代碼,就可以啟動轉換了,另一種就是硬件觸發,就是右下角部分這些觸發源,上面是注入組的觸發源,下面這些是規則組的觸發源,這些觸發源只要來自定時器,有定時器的各個通道,還有TRGO定時器主模式的輸出,定時器可以通向ADC,DAC這些外設,用于觸發轉換。那因為ADC經常需要過一個固定時間段轉換一次(比如每隔1ms轉換一次,正常思路就是,用定時器,每隔1ms申請一次中斷,在中斷里手動開始一次轉換,這樣也是可以的)但是頻繁進入中斷對我們的程序是有一定影響的,比如你有很多中斷都需要頻繁進入,那肯定會影響主程序的執行,并且不同中斷之間,由于優先級的不同,也會導致某些中斷不能及時得到響應,如果觸發ADC的中斷不能及時響應,那么我們ADC的轉換頻率就肯定會產生影響了,所以對于這種需要頻繁進中斷,并且在中斷里只完成了簡單工作的情況,一般都會有硬件的支持
在左上角這里是VREF+、VREF-、VDDA和VSSA,上面是ADC的參考電壓,決定了ADC輸入電壓的范圍,下面是ADC的供電引腳,一般情況下,VREF+要接VDDA,VREF-要接VSSA
右邊的這里的ADCCLK是ADC的時鐘,用于驅動內部逐次比較的時鐘,這個是來自ADC預分頻器,這個ADC預分頻器是來源于RCC的
DMA請求是用于觸發DMA進行數據轉運的
模擬看門狗:它里面可以存一個閾值高限和閾值底限,如果啟動了模擬看門狗,并指定了看門的通道,那這個看門狗就會關注它看門的通道,一旦超過這個閾值范圍了,它就會亂叫,就會在上面申請一個模擬看門狗的中斷,最后通向NVIC,對于規則組和注入組而言呢,它們轉換完成之后,也會有一個EOC轉換完成的信號
EOC:規則組的完成信號
JEOC:注入組完成的信號
這兩個信號會在狀態寄存器里置一個標志位,我們讀取標志位,就能知道是不是轉換結束了,同時這兩個標志位也可以去到NVIC申請中斷,如果開啟了NVIC對應的通道,它們就會觸發中斷
ADC基本結構
輸入通道
這些就是ADC通道和引腳復用的關系
這個對應關系也可以通過引腳定義表看出來
轉換模式
單次轉換,非掃描模式
這個是最簡單的
這里左邊畫了一個列表,這個表就是規則組里的菜單,有16個空位,分別是序列1都序列16,你可以在這里“點菜”就是寫入你要轉換的通道,在非掃描的模式下,這個菜單就只有第一個序列1的位置有效。這時菜單同時選中一組的方式就退化為簡單地選中一個的方式了,這里序列1的位置指定我們想轉換的通道,比如通道2,然后就可以觸發轉換,ADC就會對這個通道2進行模數轉換,過一點時間,轉換完成。轉換結果放在數據寄存器里,同時EOC標志位置1。我們判斷這個EOC標志位,如果轉換完了,那我們就可以在數據寄存器里讀取結果了,如果我們想在啟動一次轉換,那就需要在觸發一次,轉換結束,置EOC標志位,讀結果。如果想換一個通道轉換,那在轉換之前,把第一個位置的通道2改成其他通道,然后在啟動轉換,這樣就行了
連續轉換,非掃描模式
它與上一種單次轉換不同的是,它在一次轉換結束后不會停止,而是立刻開始下一輪的轉換,然后一直持續下去。這樣就只需要最開始觸發一次,之后就可以一直轉換了。這個模式的好處就是開始轉換之后不需要等待一段時間的,因為它一直都在轉換,所以你就不需要手動開始轉換了,也不用判斷是否結束的,想要讀AD值的時候,直接從數據寄存器取就是了,這就是連續轉換,非掃描的模式
單次轉換,掃描模式
這個模式也是單次轉換,所以每觸發一次轉換結束后,就會停下來,下次轉換就得在觸發才能開始,然后它是掃描模式,這就會用到這個菜單列表了,你可以在這個菜單里點菜(比如第一菜是通道2,第二菜是通道5,等等),這里每隔位置是通道幾可以任意指定,并且也是可以重復的然后初始化結構體里還會有個參數,就是通道數目,以為這16個位置你可以不用完,只用前幾個,那你就需要在給一個通道數目的參數,告訴他,我有幾個通道(比如這里指定通道數目為7,那它就只看前7個位置,然后每次觸發之后會,他就依次對這前7個位置進行AD轉換,轉換結果都放在數據寄存器里,這里為了防止數據被覆蓋,就需要用到DMA及時將數據挪走,那7個通道轉換完成之后,產生EOC信號,轉換結束,然后在觸發下一次,就又開始新一輪的轉換)這個就是單次轉換,掃描模式的工作流程
連續轉換,掃描模式
?這個模式的轉換就是在上一個的基礎上變了一點,就是一次轉換完成后,立刻開始下一次的轉換
觸發控制
這個表就是規則組的觸發源,這個表里,有來自定時器的信號,還有外部引腳或定時器的信號,這個具體是引腳還是定時器,需要用AFIO重映射來確定,最后是軟件控制位,也就是我們之間說的然軟件觸發,這些觸發信號怎么選擇,可以通過設置右邊這個寄存器來完成,當然使用庫函數的話,直接給一個參數就行了
數據對齊
?我們這個ADC是12位的,它的轉換結果就是一個12位的數據,但是這個數據寄存器是16位的,所以就存在一個數據對齊的問題
數據右對齊:就是12位的數據向右靠,高位多出來的幾位就補0
數據左對齊:就是12位的數據向左靠,低位多出來的幾位補0
在這里我們一般使用的都是第一種右對齊,這樣讀取這個16位寄存器,直接就是轉換結果
如果是左對齊,直接讀的話,得到的數據會比實際的大
轉換時間
?校準
?這個我們不需要理解,因為這個過程是固定的,我們只需要在ADC初始化的最后,加幾條代碼就行了,至于怎么計算,怎么校準的,我們不需要管,所以這個了解一下就行
硬件電路
?第一個是一個單位器產生一個可調的電壓