[STM32] 17-ADC Conversion DMA

Morgan Ting
閱益如美
Published in
10 min readNov 12, 2022
Photo by Harrison Broadbent on Unsplash

Analog to Digital Convsersion, ADC 用以測量感測器電壓,例如溫度、溼度等。ADC 量測資料可透過 Direct Memory Access, DMA 傳輸減少 CPU 負擔。本文章解紹多通道 ADC 量測以 DMA 傳輸資料,開發環境為 STM32CubeIDE 以及搭配 Hardware Abstration Layer, HAL 函式庫來完成。

文章內容

  1. STM32 DMA 簡介
  2. 實作
  3. 成果展示

工具與材料

  1. STM32CubeIDE
  2. Blue Pill ( STM32F103C8T6 ) 開發板
  3. ST-LINK v2
  4. 10K Ω 可變電阻 * 2
  5. 麵包板與單芯線

STM32 DMA 簡介

Direct Memory Access, DMA 為何物 ? 傳統處理資料的搬移或複製皆需要 CPU 參與,但是周邊裝置與 CPU 速度差異太大往往造成空等或是必須處理大小資料複製搬移。

傳統存取架構

為了改善情況,CPU 需要一個助手來分擔資料複製搬移的苦差事,於是 DMA 就此現身。有了DMA 協助後 CPU 可專注重要的事項,周邊設備的資料交由 DMA 進行傳輸。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 。
Ref : datasheet

DMA 各模組與其通道賦予不同任務,使用時須翻閱手冊了解各通道功能。

下圖為 DMA1 與 DMA2 各通道之功能。

Ref : datasheet
Ref : datasheet

實作

使用 ADC1 的 Channel_0 與 Channel_1 進行 ADC 取樣,資料以 DMA 方式傳輸並以 Live Expression 觀察轉換結果。

一、開啟 STM32CubeIDE 開發環境,建立一個新的專案。

start a project

二、選擇微處理器型號,輸入F103C8 可以快速找到,選擇該型號後按下 「Finish」鍵。

target selection

三、輸入專案名稱後按下「Finish」鍵。

project name

四、設定 SYS ,這邊的 Debug 選項選擇 「Serial Wire」。

SYS

五、RCC 時脈源,HSE 選擇 「Crystal / Ceramic Resonator」,其中 HSE 是連接開發板上的 8 MHz 震盪器提供系統使用。

RCC

六、點開 「Analog」可以看到 ADC1 與 ADC2 ,點選 ADC1 後會出現設定畫面。

這一次要使用通道 0 與通道 1 ,所以勾選 「IN0 」 與 「IN1 」。

channel

參數設定如下:

  • 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 」。
parameter

七、DMA 設定畫面,首先新增一個 DMA 項目並選擇 ADC1 。

DMA

底下的參數設定,Mode 選擇 Circular 循環模式,配合 ADC 連續取樣持續傳送轉換結果。Data Width 資料寬度選擇 Word 32 位元,因為稍待程式中我們會宣告 32 位元長度的變數來取得轉結果。

DMA

八、Clock Configuration 設定系統時脈為 72 MHz,ADC 時脈為 12 MHz 。

Clock Configuration

九、project manager 原則上不需要設定,看一下是否有異即可。

project manager

十、產生程式碼,可以按存檔鍵或是點擊上方 「Project 」=> 「Generate Code 」產生程式碼。

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 轉換結果依序放到蘿蔔坑裡面。

code

最後往下找到初始化 DMA 的部分,因為不使用中斷所以將 DMA 中斷註解不要執行。

在先前設定 DMA 時中斷不可取消,因此需在程式碼中註解避免中斷的產生。

十二、完成程式碼撰寫後進行編譯程序,按下綠色箭頭按鈕。

十三、在 Debugger 項目將 「ST-LINK S/N 」打勾並點擊右方 「SCAN」按鈕。

此時會顯示 ST-Link v2 編號,沒問題後按下 「OK 」按鈕即開始編譯並上傳程式到開發板。

十四、點擊甲蟲符號進行 Debug 程序,我們要利用 Live Expression 觀察解果。

在畫面右手邊找到 Live Expression 後新增變數,value 。

Live Expression

完成後,點擊綠色小箭頭 ( Resume ) 並將陣列變數 value 展開即可監看轉換結果。

Result

電路圖

總結

本次實驗利用 ADC_1 的 Channel_0 與 Channel_1 進行 ADC 取樣,轉換資料由 DMA 傳輸並以 Live Expression 觀察轉換結果。

本文章總結如下:

  • ADC 多通道轉換須以掃描模式進行。
  • 各轉換通道可以自行設定順序,取樣時間可以依需求有不同選擇。
  • ADC 與記憶體之間透過 DMA 傳輸資料,CPU 毋須干預。
  • 各 DMA 通道有不同功能,STM32CubeIDE 開發環境省下不少設定功夫。
  • DMA 傳輸可設定循環模式持續傳輸資料。
  • DMA 資料寬度可依來源與目的做設定。

參考資料

  1. STM32F103 手冊 [ 連結 ]
  2. STM32F1 HAL and Low-layer drivers [ 連結 ]
  3. STM32F103 電器特性 [ 連結 ]

感謝讀者

若文章有幫助到您可以拍手給我鼓勵,免費支持我。

相關文章

  • [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 [連結]

--

--

Morgan Ting
閱益如美

用好奇心探索世界。喜愛學習樂於分享。