[STM32] 17-ADC Conversion DMA
Analog to Digital Convsersion, ADC 用以測量感測器電壓,例如溫度、溼度等。ADC 量測資料可透過 Direct Memory Access, DMA 傳輸減少 CPU 負擔。本文章解紹多通道 ADC 量測以 DMA 傳輸資料,開發環境為 STM32CubeIDE 以及搭配 Hardware Abstration Layer, HAL 函式庫來完成。
文章內容
- STM32 DMA 簡介
- 實作
- 成果展示
工具與材料
- STM32CubeIDE
- Blue Pill ( STM32F103C8T6 ) 開發板
- ST-LINK v2
- 10K Ω 可變電阻 * 2
- 麵包板與單芯線
STM32 DMA 簡介
Direct Memory Access, DMA 為何物 ? 傳統處理資料的搬移或複製皆需要 CPU 參與,但是周邊裝置與 CPU 速度差異太大往往造成空等或是必須處理大小資料複製搬移。
為了改善情況,CPU 需要一個助手來分擔資料複製搬移的苦差事,於是 DMA 就此現身。有了DMA 協助後 CPU 可專注重要的事項,周邊設備的資料交由 DMA 進行傳輸。DMA 可以協助記憶體之間以及記憶體與周邊設備之間的資料傳輸。
STM32 依晶片型號有不同數量的 DMA 模組。以 STM32F103C8T6 而言共有兩組 DMA 模組可使用。其特性如下:
- 提供周邊與記憶體、記憶體與記憶體之間高速傳輸,毋須透過 CPU 干預。
- DMA1 有 7 個通道,DMA2 有 5 個通道,合計 12 個通道。
- 每個通道有專用 DMA 請求。
- 每個 DMA 模組中的通道請求優先權分為: 很高、高、中等、低。若軟體設定相同優先權則以硬體優先權為主。
- 來源與目的地的資料大小需一致,分為 Byte、half-word ( 16 Bit )、word ( 32 Bit )。
- 每個通道有3個獨立事件,DMA 半傳輸、DMA 傳輸完成、DMA 傳輸錯誤,任一事件可觸發中斷。
- 可設定資料傳輸數目,最大 65535 。
DMA 各模組與其通道賦予不同任務,使用時須翻閱手冊了解各通道功能。
下圖為 DMA1 與 DMA2 各通道之功能。
實作
使用 ADC1 的 Channel_0 與 Channel_1 進行 ADC 取樣,資料以 DMA 方式傳輸並以 Live Expression 觀察轉換結果。
一、開啟 STM32CubeIDE 開發環境,建立一個新的專案。
二、選擇微處理器型號,輸入F103C8 可以快速找到,選擇該型號後按下 「Finish」鍵。
三、輸入專案名稱後按下「Finish」鍵。
四、設定 SYS ,這邊的 Debug 選項選擇 「Serial Wire」。
五、RCC 時脈源,HSE 選擇 「Crystal / Ceramic Resonator」,其中 HSE 是連接開發板上的 8 MHz 震盪器提供系統使用。
六、點開 「Analog」可以看到 ADC1 與 ADC2 ,點選 ADC1 後會出現設定畫面。
這一次要使用通道 0 與通道 1 ,所以勾選 「IN0 」 與 「IN1 」。
參數設定如下:
- Mode 使用獨立模式 「Independent Mode」。
- Data Alignment 選擇右對齊 「Right Alignment」。
- Scan Conversion Mode 是否開啟掃描模式,在設定轉換通道數量後會自動設為 「Enabled」。
- Continous Conversion Mode 是否開啟連續轉換模式,選擇 「Enabled」。
- Discontinous Conversion Mode 是否開啟間斷模式,選擇 「Disabled」。
- Enable Regular Conversions 是否開啟常規轉換,選擇 「Enable」。
- Number of Conversion 待轉換通道數量,選擇 「2」。
- Rank 轉換通道排序,因為啟用2個通道會有2個 Rank 需要設定。Rank 1 的 Channel 選擇 「 Channel 0 」取樣時間隨意設為「71.5 Cycle 」。Rank 2 的 Channel 選擇 「 Channel 1 」取樣時間隨意設為「239.5 Cycle 」。
七、DMA 設定畫面,首先新增一個 DMA 項目並選擇 ADC1 。
底下的參數設定,Mode 選擇 Circular 循環模式,配合 ADC 連續取樣持續傳送轉換結果。Data Width 資料寬度選擇 Word 32 位元,因為稍待程式中我們會宣告 32 位元長度的變數來取得轉結果。
八、Clock Configuration 設定系統時脈為 72 MHz,ADC 時脈為 12 MHz 。
九、project manager 原則上不需要設定,看一下是否有異即可。
十、產生程式碼,可以按存檔鍵或是點擊上方 「Project 」=> 「Generate Code 」產生程式碼。
十一、在程式碼中找到 / * USER CODE BEGIN 0 * / 區段,宣告一個陣列變數稍待用來觀察結果。
uint32_t value[2] = {0};
在下方找到 / * USER CODE BEGIN 2 * / 區段,啟動帶 DMA 功能的 ADC 轉換。
HAL_ADC_Start_DMA(&hadc1, value, 2 );
參數中的 value 是我們事先宣告的陣列變數,2 表示有 2 筆資料,這樣 DMA 就會把 ADC 轉換結果依序放到蘿蔔坑裡面。
最後往下找到初始化 DMA 的部分,因為不使用中斷所以將 DMA 中斷註解不要執行。
在先前設定 DMA 時中斷不可取消,因此需在程式碼中註解避免中斷的產生。
十二、完成程式碼撰寫後進行編譯程序,按下綠色箭頭按鈕。
十三、在 Debugger 項目將 「ST-LINK S/N 」打勾並點擊右方 「SCAN」按鈕。
此時會顯示 ST-Link v2 編號,沒問題後按下 「OK 」按鈕即開始編譯並上傳程式到開發板。
十四、點擊甲蟲符號進行 Debug 程序,我們要利用 Live Expression 觀察解果。
在畫面右手邊找到 Live Expression 後新增變數,value 。
完成後,點擊綠色小箭頭 ( Resume ) 並將陣列變數 value 展開即可監看轉換結果。
電路圖
總結
本次實驗利用 ADC_1 的 Channel_0 與 Channel_1 進行 ADC 取樣,轉換資料由 DMA 傳輸並以 Live Expression 觀察轉換結果。
本文章總結如下:
- ADC 多通道轉換須以掃描模式進行。
- 各轉換通道可以自行設定順序,取樣時間可以依需求有不同選擇。
- ADC 與記憶體之間透過 DMA 傳輸資料,CPU 毋須干預。
- 各 DMA 通道有不同功能,STM32CubeIDE 開發環境省下不少設定功夫。
- DMA 傳輸可設定循環模式持續傳輸資料。
- DMA 資料寬度可依來源與目的做設定。
參考資料
感謝讀者
若文章有幫助到您可以拍手給我鼓勵,免費支持我。
相關文章
- [STM32] 00-Install STM32CubeIDE [連結]
- [STM32] 01-ST-LINK [連結]
- [STM32] 02-STM32F103C8T6 [連結]
- [STM32] 03-GPIO-Output [連結]
- [STM32] 04-GPIO-Input [連結]
- [STM32] 05-Ext-Interrupt [連結]
- [STM32] 06-Timer-Basic [連結]
- [STM32] 07-Timer-Interrupt [連結]
- [STM32] 08-Timer-Output_Compare [連結]
- [STM32] 09-Timer-PWM [連結]
- [STM32] 10-Timer-Input_Capture [連結]
- [STM32] 11-RTC-Second-Interrupt [連結]
- [STM32] 12-RTC-Alarm_Interrupt [連結]
- [STM32] 13-Independent_Watch_Dog [連結]
- [STM32] 14-Windows_Watch_Dog [連結]
- [STM32] 15-ADC_Conversion [連結]
- [STM32] 16-ADC_Conversion_Temperature_Sensor [連結]
- [STM32] 17-ADC_Convversion_DMA [連結]
- [STM32] 18-SPI [連結]
- [STM32] 19-UART [連結]
- [STM32] 20-I2C [連結]