[STM32] 15-ADC_Conversion

Morgan Ting
閱益如美
Published in
12 min readJun 5, 2022
Photo by Mika Baumeister on Unsplash

Analog to Digital Conversion , ADC 類比 — 數位轉換可將類比物理量轉換成數位訊號進行處理。STM32 提供 12 位元解析度的 ADC 轉換,用來作為電壓監測或物理性感測器訊號取樣非常方便。本文章介紹 STM32 的 ADC 功能,以 STM32CubeIDE 開發環境搭配 Hardware Abstraction Layer, HAL 函式庫進行實作。

文章內容

  1. STM32 的 ADC 介紹
  2. 轉換模式
  3. 實作
  4. 成果展示

工具與材料

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

STM32 的 ADC 介紹

Analog — Digital Conversion, ADC 是一項成熟的技術,隨著科技進步在解析度與轉換時間上有著顯著改善。STM32 內建了 ADC 功能其特性如下:

特性:

  • 12 位元解析度,轉換結果為 0 ~ 4095 。
  • 單次、連續、掃描與間斷轉換模式。
  • 16 位元資料暫存器儲存轉換結果,可設定左、右對齊格式。
  • 看門狗監測輸入電壓是否超過上、下限。
  • 由 PCLK2 提供時脈源,不可超過 14 MHz。
  • 可藉由外部觸發轉換。
  • ADC 電源 2.4 v ~ 3.6 v 。
  • ADC 待測電壓範圍 Vref — < Vin < Vref + 。

STM 32 的 ADC 系統方塊圖

reference: datasheet

STM32F103C8T6 ADC 通道對應的腳位

ADC Pin

通道分組

STM32 提供了多個通道進行 ADC 轉換,應用上可分成兩組搭配使用。

  • Regular Channels 常規通道 : 一般轉換工作皆使用常規通道,用於循序性的轉換程序。
  • Injected Channels 注入通道 : 相當於 「 插隊 」,在常規通道轉換期間插隊進行注入通道的轉換,完成注入通道轉換後再回到常規通道進行轉換,由於是用來插隊的功能因此要有觸發源來啟動注入轉換。

轉換時間

ADC 轉換時間 = 取樣時間 + 12.5 個週期

其中取樣時間有以下選擇,一般而言取樣時間長越準確。

1.5、7.5、13.5、28.5、41.5、55.5、71.5、239.5 個週期。

範例: 設 ADCCLK = 12 MHz ,取樣時間設為 13.5 個週期,則

ADC 轉換時間為 1 / 12 * ( 13.5 + 12.5 ) = 0.083 u * 26 = 2.17 us

換算結果

ADC 的解析度是 12 位元,2 的 12 次方是 4096 代表會將物理量分成 4096 等分,以 STM32 而言 ADC 的參考電壓如果相同於電源電壓 3.3 v ,那麼 1 等分就是 3.3 / 4096 = 0.806 mv。

轉換後的數值與待測電壓的換算就是 待測電壓 = ( 轉換數值 * 3.3 ) / 4096 。

轉換模式

一、Single Conversion Mode 單次轉換模式

單次轉換模式,可以軟體啟動或外部觸發啟動,ADC 只執行一次轉換在完成後隨即停止。

完成轉換後將結果儲存在 16 位元的 暫存器 ADC_DR 中,並設立 End of Conversion, EOC 旗標。

reference : AN3116 Application Note

二、Continous Conversion Mode 連續轉換模式

連續轉換模式,可以軟體啟動或外部觸發啟動 在完成一次轉換後隨即進行下一次轉換並且不間斷,可用在需要連續監控的場合。

reference : AN3116 Application Note

三、Scan Mode 掃描模式

掃描模式,可以對一組通道依自訂順序做轉換。掃描模式需啟用 DMA 來傳遞轉換結果。

reference : AN3116 Application Note

四、Discontinous Mode 間斷模式

透過觸發來啟動轉換,可以將排定的轉換通道分組進行轉換,每觸發一次便轉換一組。

例如:有數個轉換通道 0、1、2、3、4、7、9、10,以 3 個通道為一組。

  • 第一次觸發,轉換通道 0、1、2。
  • 第二次觸發,轉換通道 3、4、7。
  • 第三次觸發,轉換通道 9、10。並設立轉換完成旗標 EOC。

完成一輪轉換後不會自動下一輪轉換,等到第四次觸發產生才從 0、1、2 通道開始新一輪轉換。

綜合上述,應用上可以搭配不同轉換模式達到需求。

  • 單通道單次轉換 ( 單次轉換模式 )。
  • 單通道連續轉換 ( 連續轉換模式 )。
  • 多通道單次轉換 ( 掃描模式 + 單次轉換模式 )。
  • 多通道連續轉換 ( 掃描模式 + 連續轉換模式 )。
  • 間斷轉換。

實作

本次實驗使用可變電阻進行電位調整,可變電阻上的電壓 0 ~ 3.3 v ,而 ADC 參考電源為 3.3 v,因此當我們轉動可變電阻時預期會得到 0 ~ 4095 之間的轉換結果。電路設計上使用一個可變電阻連接至 STM32 的 PA0取樣通道,並利用 HAL 函式庫來完成程式撰寫。

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

start new project

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

select MCU

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

project name

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

serial wire

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

clock source

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

PA1 腳位對應 ADC 的 Channel 0,所以選擇 「IN0」。

參數設定如下:

  • Mode 使用獨立模式 「Independent Mode」。
  • Data Alignment 選擇右對齊 「Right Alignment」。
  • Scan Conversion Mode 是否開啟掃描模式,選擇 「Disabled」。
  • Continous Conversion Mode 是否開啟連續轉換模式,選擇 「Enabled」。
  • Discontinous Conversion Mode 是否開啟間斷模式,選擇 「Disabled」。
  • Enable Regular Conversions 是否開啟常規轉換,選擇 「Enable」。
  • Number of Conversion 待轉換通道數量,選擇 「1」。
  • Rank 轉換通道排序,因為只用一個通道所以只會顯示一個,若啟用多通道那麼就會有多個 Rank 需要設定。Rank 1 的 Channel 選擇 「Channel 0 」。Sampling Time 取樣時間,可依需求選擇,這裡選擇 「7.5 Cycle」。
select ADC channel
parameter

開啟 ADC 中斷

enable interrupt

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

clock configuration

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

Generate Code

九、產生程式碼後便可開始撰寫程式,首先宣告兩個變數分別用來儲存 ADC 轉換結果以及換算成對應的電壓。在 * USER CODE BEGIN 0 * 區段宣告兩個變數。

uint32_t ADC_Result = 0;float ADC_Voltage = 0;
variables for ADC convertion

在 USER CODE BEGIN 2 區段進行 ADC 校正後啟動帶有中斷的 ADC 轉換功能。

HAL_ADCEx_Calibration_Start(&hadc1);HAL_ADC_Start_IT(&hadc1);
start ADC with interrupt

因為要利用中斷所以要找到 Call Back 函式,在左邊的 Project Explore 點開路徑,Core => Src => STM32f1xx_it.c 找到 ADC_1_2_IRQHandler(void),滑鼠點兩下即開啟該函式所在位置。

IRQ function

之後將 「HAL_ADC_IRQHandler」以滑鼠選起來後按滑鼠右鍵,選擇 Open Decaration 開啟該函式所在位置,找到 「void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)」即是我們要找的 Call Back 函式。

call back function

將其複製後貼到 main.c 主程式下方的 USER CODE BEGIN 4 區段。其中,要將最後的 hadc 改成 hadc1,並寫下程式敘述

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1){ADC_Result = HAL_ADC_GetValue(hadc1); // 取得轉換結果存到變數 ADC_ResultADC_Voltage = (float)ADC_Result * 3.3 / 4096; // 換算成對應電壓}

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

run code

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

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

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

debug

在畫面右手邊找到 Live Expression 後新增兩個變數,ADC_Result , ADC_Voltage。

Live Expression

完成後,點擊綠色小箭頭 ( Resume ) 即可開始監看變數內容。由於是連續模式所以會一直顯示轉換結果,當轉動可變電阻時可以觀察到數值跟著改變。

result

電路圖

schematic

成果展示

這次實驗使用一個可變電阻以連續轉換模式監看電壓。轉換完成後啟動中斷並在中斷回調函式中取得結果並進行換算,此種方式並不甚好,因為 ADC 轉換很快,以此設定而言,ADC 時脈為 12 MHz ,取樣時間設定 7.5 個週期,依公式可以得到轉換時間為 1 / 12 * ( 7.5 + 12.5 ) = 0.083 u * 20 = 1.67 us 如此頻繁進行中斷會造成負擔。然而對於單通道這樣簡單的應用,採用輪詢或中斷是最簡單的方式。

總結

STM32 提供多通道 ADC 取樣,在轉換時間與解析度皆能應付一般所需。本文章總結如下。

  • 12 位元解析度,將待測電壓分為 4096 等分。
  • 取樣頻率由 PCLK2 提供,最高可達 14 MHz 。
  • 16 位元儲存轉換結果,可選擇左、右對齊格式。
  • 單次、連續、掃描與間斷轉換。
  • 阻斷 ( Block ) 、中斷 ( Interrupt ) 與 DMA ( Direct Memory Access ) 等方式傳遞轉換結果。

參考資料

  1. STM32F103 手冊 [ 連結 ]
  2. STM32F1 HAL and Low-layer drivers [ 連結 ]
  3. AN3116 Application Notes [ 連結 ]

相關文章

  • [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
閱益如美

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