在實際的開發中需要使用各式各樣的傳感器,這些傳感器可以采集周圍的環境信息,比如溫度、濕度、氣壓、光照等,這些信息本質上是物理的模擬信號,計算機處理信息時對數字信號比較敏感,因此把模擬信號轉換為數字信號是有必要的。ADC就起到了這樣的作用,本節將對ADC功能原理以及ADC數據采集時涉及到的DMA技術進行詳解。
- ADC的概念:Analog-to-Digital Converter的縮寫。指模/數轉換器或者模擬/數字轉換器。是指將連續變量的模擬信號轉換為離散的數字信號的器件。
- ADC的作用:采集傳感器的數據,測量輸入電壓,檢查電池電量剩余,監測溫濕度等。典型的模擬數字轉換器將模擬信號轉換為表示一定比例電壓值的數字信號。
- ADC的性能指標:
量程:能測量的電壓范圍,一般來收量程越大越好
分辨率:ADC的分辨率通常以輸出二進制數的位數表示,位數越多,分辨率越高,精度越大,外部微小的變化都可以被顯示。一般來說分辨率越高,轉化時間越長。
轉化時間:模擬輸入電壓在允許的最大變化范圍內,從轉換開始到獲得穩定的數字量輸出所需要的時間稱為轉換時間,希望時間越短越好。
- STM32F4的ADC配置:
STM32F40X有3個ADC,每個可配置 12 位、10 位、8 位或 6 位分辨率
每個ADC 有16個外部通道。另外還有兩個內部 ADC源(直接測量內部溫度和電壓信號) 和 V BAT 通道(測量電池的剩余電量)掛在 ADC1上
這些通道的 A/D 轉換可以單次、連續、掃描或間斷模式執行。
ADC具有獨立模式(單個ADC工作)、雙重模式(兩個ADC配合工作完成采樣)和三重模式(三個ADC配合工作完成采樣),對于不同 AD轉換要求幾乎都有合適的模式可選
ADC 的結果可以左對齊或右對齊方式存儲在 16 位數據寄存器中。采集到的數據精度最大為12位,不夠16位,因此,需要選擇合適的存儲方式。
- ADC功能框圖分析:
1、電壓輸入范圍:ADC 輸入范圍為:V REF- ≤ V IN ≤ V REF+ 。由 V REF- 、V REF+ 、V DDA 、V SSA 、這四個外部引腳決定。我們在設計原理圖的時候一般把 V SSA 和 V REF- 接地,把 V REF+ 和 V DDA 接 3.3V,得到ADC 的輸入電壓范圍為:03.3V。如果我們想讓輸入的電壓范圍變寬,去到可以測試負電壓或者更高的正電壓,我們可以在外部加一個電壓調理電路(線性的轉換關系,如根據一定的轉換關系將-10V10V轉換為03.3V),把需要轉換的電壓抬升或者降壓到 03.3V,這樣 ADC 就可以測量了
2、輸入通道:每個ADC 有16個外部通道。特別是ADC1還有兩個內部 ADC 源 和 V BAT 通道掛在 ADC1上,V BAT 通道也屬于內部通道,兩個內部 ADC 源沒有對應外部管腳,直接測量內部信息。一個連接內部溫度傳感器,主要測量CPU以及芯片內部的一些關鍵電路的溫度。另一個連接VREFINT,測量電源模塊的電壓值,V BAT 通道用來測量備用電池的電池容量。
3、轉換順序
a.規則通道組:顧名思意,規則通道就是很規矩的意思,我們平時一般使用的就是這個通道。相當于正常運行的程序,最多16個通道,在使用過程中按順序進行轉換,按順序采集完一個通道進行轉換后再采集下一個通道進行轉換。規則通道和它的轉換順序在ADC_SQRx寄存器中選擇,規則組轉換的總數應寫入ADC_SQR1寄存器的L[3:0]中。
ADC像這樣的規則序列寄存器有3個,每個規則序列寄存器都能設定第n次轉換的具體通道,共有16個外部通道,最多設置16次。如上圖,規則序列寄存器3(ADC_SQR3)可以設定第一次到第六次順序轉換的通道,規則序列寄存器2(ADC_SQR2)可以設定第七次到第十二次順序轉換的通道,規則序列寄存器1(ADC_SQR1)可以設定第十三次到第十六次順序轉換的通道,且ADC_SQR1寄存器的L[3:0]中(20位到23位)用來設定要順序轉換的通道個數。例:有如下轉換順序要求,有4個通道,第一次轉換通道2,第二次轉換通道3,第三次轉換通道4,第四次轉換通道1,則ADC_SQR1寄存器的L[3:0]的值位0100,ADC_SQR3中SQ1的值設為2,SQ2的值設為3,SQ3的值設為4,SQ4的值設為1。具體的操作在Cube MX中可以配置
b.注入通道組:注入,可以理解為插入,插隊的意思,是一種不安分的通道。相當于中斷。最多4個通道。把某一通道配置位注入通道時,它的優先級就比規則通道高,暫停規則通道組的工作,優先轉換注入通道組采集到的信號。注入組和它的轉換順序在ADC_JSQR寄存器中選擇。注入組里轉化的總數應寫入ADC_JSQR寄存器的L[1:0]中。該通道組的配置方法于規則通道組相同。
4、轉換時間:ADC 輸入時鐘 ADC_CLK 由 PCLK2 經過分頻產生,最大值是 36MHz,即最大工作時鐘不能超過36MHz,典型值為30MHz。對于 STM32F407我們一般設置PCLK2=HCLK/2=84MHz,最少需要4分頻。所以程序一般使用 4分頻或者 6分頻。
ADC 的總轉換時間Tconv = 采樣時間 + 12個周期(轉換時間),采樣時間最少不小于3個ADC_CLK,轉換時間一般就是12個ADC_CLK,如果對時間沒有太過苛刻的要求,應當把采樣時間設置的稍長一些,這樣得到的結果才會更加準確。最小采樣時間: T =3 + 112= 15個周期=0.42us(ADC時鐘=36MHz下得到)。
5、數據寄存器:規則數據寄存器 ADC_DR
ADC_DR只有一個,是一個32 位的寄存器,只有低 16 位有效并且只是用于獨立模式存放轉換完成數據。因為 ADC 的最大精度是 12 位,ADC_DR 是16 位有效,這樣允許 ADC存放數據時候選擇左對齊或者右對齊,具體是以哪一種方式存放,由 ADC_CR2的 11 位 ALIGN 設置。對于規則通道組來說,所有的規則通道都使用這一個數據寄存器,實際采樣點時候,如果開啟了多個通道,每轉換完成一個通道要及時把數據從寄存器中取走。如果不及時取走,下一次轉換完成的數據就會覆蓋原數據。而對于注入通道組來說,每一個注入通道都對應一個數據寄存器。
使用 DMA:由于規則通道組只有一個數據寄存器,因此,對于多個規則通道的轉換,使用 DMA 非常有幫助。這樣可以避免丟失在下一次寫入之前還未被讀出的 ADC_DR 寄存器中的數據。在使能 DMA 模式的情況下(ADC_CR2 寄存器中的 DMA 位置 1),每完成規則通道組中的一個通道轉換后,都會生成一個 DMA 請求。
6、中斷
a.轉換結束中斷:規則通道和注入通道的數據轉換結束后,都可以產生中斷。通道轉換完成后,ADC 狀態寄存器 ADC_SR的EOC位會置1,可以不斷輪詢此位來判斷是否觸發中斷,也可以使能中斷,完成后就根據此位的狀態觸發中斷。此中斷的使用是最多的,可以在此中斷處理程序中獲取我們想要采集的數據。
b.模擬看門狗中斷:當被 ADC 轉換的模擬電壓低于低閾值或者高于高閾值時,就會產生中斷
c.溢出中斷:如果發生 DMA傳輸數據丟失,會置位 ADC 狀態寄存器 ADC_SR的 OVR位,如果同時使能了溢出中斷,那在轉換結束后會產生一個溢出中斷。
d.DMA 請求:規則和注入通道轉換結束后,除了產生中斷外,還可以產生 DMA請求,把轉換好的數據直接存儲在內存里面。
7、觸發源
a.軟件觸發:ADC轉換可以由ADC 控制寄存器 2: ADC_CR2的 ADON這個位來控制,寫 1的時候開始轉換,寫 0 的時候停止轉換。此方法使用最多
b.外部事件觸發:觸發包括內部定時器觸發和外部 IO觸發。觸發源有很多,具體選擇哪一種觸發源,由 ADC控制寄存器ADC_CR2的 EXTSEL[2:0]和 JEXTSEL[2:0]位來控制
- ADC的工作模式
單次轉換模式:ADC每次工作只轉換一次,至于這一次轉換幾個通道并不關心,如果想要再次轉換,必須重新啟動ADC。
連續轉換模式:在連續轉換模式下,ADC結束一個轉換后立即啟動一個新的轉換,直到用戶想要停止為止。(僅適用于規則通道)。
掃描模式:該模式主要針對多個通道進行轉換。例如使用單次轉換模式又開啟掃描模式,從第1個通道開始掃描,掃描第n個通道結束后不再掃描;如果使用單次轉換模式而不開啟掃描模式,這多個通道很有可能只轉換第1個通道;使用連續轉換模式又開啟掃描模式,從第1個通道開始掃描,掃描第n個通道結束后再從第1個通道開始掃描,循環往復。
不連續采樣模式:有多個通道需要轉換,此模式下一次只轉換其中的幾個,這個值n需要用戶自己設定,假設有0、1、2、3、6、7、9、10這幾個通道需要轉換,n設置為3,則
- STM32ADC單通道采集實例
實驗:利用ADC采集FSM4中電位器的數據
說明:電位器本質上就是一個滑動變阻器,通過調節電阻就可以輸出不同的電壓值,電壓值通過PC3進入ADC的輸入通道。
步驟:
1.配置RCC,ADC依賴于時鐘APB2
2.配置PC3為ADC1的通道13
3.配置ADC1
4.使能中斷,轉換完成觸發中斷
5.編寫代碼
//main.c
uint32_t adc_value = 0;//全局變量外部才可以使用
int main(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();//ADC1初始化配置,仍然采用結構體元素賦值的形式
MX_USART1_UART_Init();
while(){
/***方法一:輪詢采集ADC的值,也就是輪詢判斷EOC是否置位***/
//置位說明轉換完成就可以讀值
//啟動ADC1,軟件觸發方式,將對應的啟動位置位
HAL_ADC_Start(&hadc1);
//HAL_ADC_PollForConversion(&hadc1, 100)該函數內部循環判斷
//EOC是否置位,沒有置位就一直等待,直到超時
if( HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK ){
adc_value = HAL_ADC_GetValue(&hadc1);//讀取數據寄存器里的值
printf("adc_value = %dn",adc_value);
}
HAL_Delay(1000);//每過1s鐘重新啟動ADC
/***方法二:轉換完成后觸發中斷,在中斷中接收數值***/
HAL_ADC_Start_IT(&hadc1);//啟動ADC1并使能中斷
HAL_Delay(1000);//每過1s鐘重新啟動ADC
}
}
//adc.c
//重寫轉換結束中斷回調函數,這里對應方法二
extern uint32_t adc_value;//全局變量
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if(hadc- >Instance == ADC1) {
adc_value = HAL_ADC_GetValue(&hadc1);//讀取數據寄存器里的值
printf("adc_value = %dn",adc_value);
}
}
- STM32 ADC多通道采集實例
實驗要求:利用ADC采集電位器及STM32內部溫度傳感器的數據。
說明:采集內部溫度傳感器使用的是內部專用通道,選擇通道16或者通道18均可采集內部溫度,需要注意的是,實際中多路通道的采集一般使用DMA來進行數據的搬移,因為規則通道的數據寄存器只有一個,如果不及時取走數據,上一次采集的數據可能被覆蓋,DMA的知識將在后期進行講解,因此本節仍采用輪詢的方式查詢標志位,及時將數據取出。
步驟:
1.配置時鐘RCC
2.配置PC3位ADC1的通道13,配置內部溫度傳感器通道.
3.配置ADC
4.編寫代碼
//mian.c
int main(){
uint32_t adc_value = 0;
uint8_t i;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
while(){
//啟動ADC1,軟件觸發方式,將對應的啟動位置位
HAL_ADC_Start(&hadc1);
for(i=0;i< 2;i++){ //使用了幾個通道就應該輪詢幾次
//首先采集外部通道電位器的數值,第二次采集內部溫度傳感器的值
//HAL_ADC_PollForConversion(&hadc1, 100)該函數內部循環判斷
//EOC是否置位,沒有置位就一直等待,直到超時
if( HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK ){
adc_value = HAL_ADC_GetValue(&hadc1);//讀取數據寄存器里的值
printf("adc_value = %dn",adc_value);
}
}
HAL_Delay(1000);//每過1s鐘重新啟動ADC
}
}
- STM32數據搬運工DMA專題講解
DMA專門用于數據搬運,在開發中經常會遇到外設與內存、內存與內存進行大量的數據交互的情況,這些情況一般都是由CPU進行控制的,如果數據交互非常頻繁且數據量巨大,那么CPU就會被大量占用用于數據交互而無法完成其他工作,為了把CPU從這種單一繁瑣的工作中釋放出來,很多微控制器中都有專門用于數據交互的器件,就是DMA。
DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA 傳輸方式無需 CPU 直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAM 與 I/O 設備開辟一條直接傳送數據的通路,無需CPU的參與,CPU將這條通路的控制權釋放,轉交由DMA控制器控制,能使 CPU 的效率大為提高。DMA控制器只用于數據交互,無其他功能。
- STM32F4-DMA功能框圖分析
①外設通道:STM32F4xx 系列資源豐富,具有兩個 DMA 控制器,同時外設繁多,為實現正常傳輸,DMA需要通道選擇控制。每個 DMA控制器具有 8個數據流,每個數據流對應 8個外設請求。
外設通道選擇要解決的主要問題是決定哪一個外設作為該數據流的源地址或者目標地址。宏觀上一個數據流的所有通道可以同時工作,微觀上通道異步前進進行工作,或者根據通道優先級進行工作
DMA1外設通道表如下:
DMA2外設通道表如下:
每個數據流都與一個 DMA 請求相關聯,此 DMA 請求可以從 8 個可能的通道請求中選出。此選擇由 DMA_SxCR 寄存器中的 CHSEL[2:0] 位控制,3位用來控制8個通道的選擇。
②數據流仲裁:一個 DMA控制器對應 8個數據流,數據流包含要傳輸數據的源地址、目標地址、數據長度等等信息。如果我們需要同時使用同一個DMA 控制器(DMA1 或 DMA2)多個外設請求時,那必然需要同時使用多個數據流,那究竟哪一個數據流具有優先傳輸的權利呢?這就需要仲裁器來管理判斷
每個數據流的優先級都可以通過配置 DMA_SxCR寄存器 PL[1:0]位,設置為非常高、高、中和低四個級別,由于8個數據流只有4個優先級,如果兩個或以上數據流軟件設置優先級一樣,則他們優先級取決于數據流編號,編號越低越具有優先權。
③數據FIFO:每個數據流都有一個獨立的 4 字 FIFO(先進先出存儲器緩沖區), DMA傳輸具有 FIFO模式和直接模式。
a.直接模式:每個 DMA 請求會立即啟動對存儲器的傳輸。當在直接模式(禁止 FIFO)下將 DMA請求配置為以存儲器到外設模式傳輸數據時,DMA 僅會將一個數據從存儲器預加載到內部 FIFO,從而確保一旦外設觸發 DMA 請求時則立即傳輸數據。
b.FIFO模式:可通過控制寄存器 DMA_SxFCR 的 FTH[1:0]位來設置FIFO 閾值級別為 FIFO 大小的 1/4、1/2 或 3/4。如果數據存儲量達到閾值級別時,FIFO 內容將傳輸到目標中。如果對傳輸速度要求不是很苛刻,建議使用此模式、直接模式傳輸效率太低,一次傳輸的數據量少而工作量大。
④存儲器端口:DMA 控制器提供兩個 AHB 主端口,分別為AHB 存儲器端口(用于連接存儲器)和 AHB 外設端口(用于連接外設)。存儲器端口用來連接外部存儲器,實現內存與外存的數據交互。
⑤外設端口:用于連接外設,實現內存與外設的數據交互.
注意:DMA1 控制器 AHB 外設端口與 DMA2 控制器的情況不同,DMA1 控制器 AHB 外設端口沒有連接到總線矩陣,因此,僅 DMA2 數據流能夠執行存儲器到存儲器的傳輸,DMA1 不能實現存儲器到存儲器傳輸。
- STM32F4-DMA傳輸
1.傳輸模式 :DMA1 只有外設到存儲器和存儲器到外設兩種模式,DMA2 除前面兩種傳輸模式外還支持存儲器到存儲器的傳輸模式。模式選擇可以通過 DMA_SxCR 寄存器的 DIR[1:0]位(方向選擇,規定誰是源,誰是目的)進行控制。
2.DMA傳輸模式的源、目的、長度:
a.DMA_SxPAR寄存器: 設置外設寄存器地址
b.DMA_SxM0AR寄存器:設置存儲器地址
c.DMA_SxCR 寄存器 :DIR[1:0]位配置數據的傳輸方向
d.DMA_CNDTRx 寄存器:寫入需要傳輸的數據量, (0 到 65535),注意是數據的一個量,單位并不是字節
e.DMA_SxCR 寄存器中的 PSIZE 和 MSIZE 位:設置源和目的的數據寬度,兩邊的位寬盡量保持一致,位寬只一次傳輸多大的位寬(如一次傳輸2字節,位寬16位),如果不能保持位寬,很有可能造成數據丟失,應當開啟FIFO模式,保證數據不丟失。
3.DMA增量設置:
a.根據設置 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態,外設和存儲器指針在每次傳輸后可以自動向后遞增或保持常量。
b.當設置為增量模式時,下一個要傳輸的地址將是前一個地址加上增量值,增量值取決與所選的數據寬度為1字節(8位) 、2 字節(16位)或 4字節(32位) 。如果不啟動,每一次取很有可能只取首地址對應數據,而不會向后取值。
c.一般情況下外設并不需要遞增,每一次都是同一個地址,要不要配置外設的增量模式依具體情況而定。
4.DMA循環模式:
a.循環模式用于處理循環緩沖區和連續的數據傳輸 ( 如 ADC 的連續循環掃描模式 ) 。可以使用 DMA_SxCR 寄存器中的 CIRC 位使能此特性。
b.當啟動了循環模式,一組的數據傳輸完成時,計數寄存器將會自動地被恢復成配置該通道時設置的初值, DMA 操作將會繼續進行。
5.DMA單次傳輸和突發傳輸:
a.DMA傳輸類型有單次(Single)傳輸和突發(Burst)傳輸。DMA 控制器可以產生單次傳輸或 4 個、8 個和 16 個節拍的增量突發傳輸。一個節拍對應著用戶配置的一個數據寬度,一般突發傳輸要配合FIFO來使用,突發傳輸的數據量不可能超過FIFO的大小
b.突發大小通過軟件針對兩個 AHB 端口獨立配置,配置時使用 DMA_SxCR 寄存器中的MBURST[1:0] 和 PBURST[1:0] 位。
c.為確保數據一致性,形成突發的每一組傳輸都不可分割:在突發傳輸序列期間,AHB 傳輸會鎖定,并且 AHB 總線矩陣的仲裁器不解除對 DMA 主總線的授權。
6.DMA中斷: 對于每個 DMA 數據流,可在達到半傳輸、傳輸完成、傳輸錯誤、FIFO 錯誤(上溢、下溢或 FIFO 級別錯誤)、直接模式錯誤時產生中斷。這些標志位都在中斷狀態寄存器DMA_xISR中設置。
- ADC_DMA多路采集實例
實驗要求:利用ADC采集電位器以及芯片內部溫度傳感器的數據,在main函數中啟動ADC轉換以及DMA傳輸,最后在DMA完成中斷中打印采集到的數據。
說明:之前使用ADC采集兩路數據是使用輪詢的方式判斷采集,需要CPU一直去判斷,消耗CPU資源,顯然這并不是ADC多路采集最好的辦法,ADC多路采集一般使用DMA來進行傳輸,規則通道組采集數據時只有一個數據寄存器ADC_DR,讀取數據不及時很有可能發生數據覆蓋。
采用DMA傳輸,每當一路數據采集完成后都會產生一個DMA請求,及時把數據寄存器中的值搬移到內存中相應的buffer中去
步驟:
1.配置RCC
2.配置PC3位ADC1的通道13,配置內部溫度傳感器通道
3.配置DMA
4.配置ADC
5.配置中斷
5.編寫代碼
//main.c
uint16_t adc_value[2] = {0};//定義一個全局的接受區域,以便外部調用
int mian(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_ADC1_Init();
printf("this is adc dma testn");
while(1){
//此函數既啟動ADC,又使能DMA
HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_value, 2);
//2表示傳輸了2個數據的量,一個量是我們設定的位寬
//內部有一個專門的寄存器來記錄這個量,每傳輸完成一次,寄存器的值減1
//減到0就會觸發DMA的傳輸完成中斷
HAL_Delay(1000); //每過1s啟動一次
}
}
關于DMA傳輸完成中斷處理函數是哪一個,先將函數HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_value, 2);追進去可以看到一段代碼設置了DMA傳輸完成的回調函數,將這個函數賦給了一個指針,這個指針是DMA_Handle下的一個指針,DMA可以用于很多的外設,不同的外設的轉換完成函數是不一樣的,DMA沒有一個固定的處理函數,這個函數需要在外設配置的時候自己去初始化,DMA只提供一個接口,一個傳輸轉換完成的函數指針,不同的外設對這個結構賦不同的處理函數的指針,這里對ADC來說自己封裝了一個DMA傳輸完成處理中斷的函數,當DMA傳輸完成中斷觸發的時候自己去調用這個接口下的對應的函數。ConvCplt的意思是ConverseComplete
將void DMA2_Stream0_IRQHandler(void)這個中斷處理函數入口追進去可以看到DMA有各種不同的中斷處理請求,我們在傳輸完成中斷***Transfer Complete Interrupt management***這一部分里可以看到hdma->XferCpltCallback(hdma);這樣一個指針函數,但是用戶無法使用這個指針函數,這個指針在HAL_ADC_Start_DMA(&hadc1, (uint32_t*) 這個函數中已經賦值,實際上這個函數最終進入了HAL_ADC_ConvCpltCallback函數,也就是ADC傳輸完成函數。
//adc.c
extern uint16_t adc_value[2] ;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
//每一次采集完成后都會將數據傳輸到value中
if(hadc- >Instance == ADC1) {
printf("adc_value[0]=%d, adc_value[1]=%dn",adc_value[0],adc_value[1]);
}
}
-
dma
+關注
關注
3文章
552瀏覽量
99954 -
STM32F4
+關注
關注
3文章
194瀏覽量
27894 -
模擬數字轉換器
+關注
關注
1文章
74瀏覽量
12439 -
ADC采樣電壓
+關注
關注
0文章
4瀏覽量
2803 -
信號采集傳感器
+關注
關注
0文章
2瀏覽量
1223
發布評論請先 登錄
相關推薦
評論