CubeIDE Note 06: Lesson 4. ADC Setting And Application for LL Library
教學
如何使用 CubeIDE 設定 ADC 基本應用
環境
本文使用
OS: Windows x64
STM32CubeIDE Version: 1.6.1
開發板: NUCLEO-F334R8(STM32F334R8)
Low-Layer (LL) Library
教學文章列表
參考資料
UM2570. Description of STM32G4 HAL and low-layer drivers
RM0364. STM32F334xx advanced Arm®-based 32-bit MCUs
Datasheet. STM32F334x4 STM32F334x6 STM32F334x8
ADC — 成大資工 wiki
【STM32】ADC的基本原理、暫存器(超基礎、詳細版)
STM32 ADC詳細篇(基於HAL庫)
Section 1. 基本題
設定HRTIM之Timer Master為ADC觸發源,頻率100kHz
將ADC1_IN1(PA0)腳位設定為一般通道,輸入0~3V電壓,
且利用Live Expression,即時監測A/D暫存器所讀取之數值,
並以PA4腳位測試ADC轉換時間。
提示
使用 Timer Master中斷與 ADC中斷測量 ADC轉換時間
Section 1.1 ADC介紹
STM32F334具有兩顆ADC,最大解析度皆為12bit(10, 8, 6可設定)
ADC1 有11個 External channels,3個Internal channels
ADC2 有14個 External channels,3個Internal channels
分為Fast channels (5.1 Ms/s)與Slow channels(4.8 Ms/s)
每個通道可設定Single-ended 或 differential inputs,
每個ADC可針對單通道轉換或整個通道序列轉換,
可設定連續轉換或單次觸發轉換,
每個ADC都有三個analog watch dog,
支援2V~3.6V電壓,詳情請參閱RM0364手冊
V_REFINT: 實際電壓不一定是 3.3V,透過測量來校準值 。
在 DISCO板子上面,V_REF+ = VDDA = VDD = 2.95V (3V)
在 NUCLEO-F334R8 上面量到 3.42V
ADC channel 6~9為 ADC1 與 ADC2 共用
ADC都在APB2上面,Clock來自APB2,頻率為
ADC Clock = APB2 Clock / Analog Prescalar
A. Regular channels 與 Injected channels
每個 channel 都能設為 Regular(一般)或 Injected(注入),
Regular 在啟動後會依序進行轉換,
而 Injected 表示會等待外部訊號觸發轉換,
觸發後以 Injected 的轉換為優先處理,可中斷Regular channel。
B. 暫存器介紹
Regular channel 中的轉換順序由三個暫存器控制:SQR1、SQR2、SQR3。 SQR暫存器控制著轉換通道的數目和轉換順序,只要在對應的暫存器位置SQRx中寫入相應的通道號碼,這個通道就是第x個轉換。Injected channel也是同理。
通常取樣時間越長,得到的值越精確
轉換時間 = 採樣時間 + 12.5 clock cycles
C. 轉換時序與中斷介紹
EOC 即 End of Conversion (為 Regular Group 結束轉換時產生之中斷)
當 ScanConvMode Disable 時(也就是 Regular Group 只有一個channel),每次轉換結束都會產生 EOC 中斷。
當 ScanConvMode Enable 時,只有當所設定之 Regular Group 之最後一個 channel 完成轉換時才會產生 EOC。
JEOC 為 Injected Group 結束轉換時產生之中斷。
AWD 為 analog watchdog 所產生之中斷。
D. 外部觸發事件
不同模式只能被特定事件觸發
E. 轉換模式介紹
可參考成大資工wiki用流程圖講得很清楚
筆者自己做出的結論:
Single conversion mode
單次轉換,觸發一次只轉換一個通道
Continuous conversion mode
連續轉換,轉換完成一個通道後立即自動執行下一個通道的轉換,直到序列全部完成轉換停止
Scan mode
掃描模式,觸發後,自動的連續讀取多個通道,且不斷重新開始新的序列
Discontinuous conversion mode
間斷模式,觸發後,可分組分批進行轉換
F. 兩ADC工作模式
Section 1.2 Live Expression介紹
Live Expression是一個可以即時監控運行變數的功能
開啟程式碼優化的話會無法使用此功能
開啟方式要在Debug Configuration裡面先確保有開啟相關設定
然後在 Debug 時在旁邊就可以看到相關的功能卡
輸入想看的變數,就可以即時監控變數值
若 Live Expression 功能卡不見的話
可以透過Window >> Show View >> Live Expression,把它叫出來
Live Expression(不知道甚麼鬼翻譯變:現場表達式)
Section 1.3 CubeMX設定
Step 1. 請先按照此篇教學(選對開發板)做好基礎設定
Step 2. 把需要的IO設定好
基本題用PA0做ADC輸入,PA4做GPIO輸出
我們從 Pinout view 把它設定好即可
PA0 選 ADC1_IN1
PA4 選 GPIO_OUTPUT
Step 3. ADC觸發源 Timer Master 之設定
基本題使用HRTIM的Timer Master模組作為ADC觸發源
我們切換到HRTIM1設定頁
勾選 Master Timer Enable
跟 Lesson 3 一樣,切回去Clock Configuration
可看到HRTIM1時脈設定已啟用
我們把它的選擇線調到 PLLCLK*2
讓 HRTIM1 時脈為 144 MHz
HRTIM 之 Master Timer 頻率設定 100kHz
可參照Lesson 3. 設定介紹
Period 設為 46080 ( = 4.608GHz / 100kHz)
Preload: Enable
Repetition Update: Enable
切換到ADC Triggers Configuration 分頁
根據Section 1.1.D 觸發事件表格
ADC Regular channel 只能使用 ADC Trigger 1, 3 觸發
所以我們這邊使用ADC Trigger 1 來觸發
觸發源選擇 Timer Master 週期更新事件
ADC Trigger Configuration: Enable
Update Trigger Source: Master Timer
Timer Sources Selection: 1 (ADC Trigger on master period)
Step 4. ADC 設定
基本題我們要使用ADC1_IN1
我們切換到ADC1,把Channel IN1 設定為Single-ended (單端輸入)
因為我們只轉換一個通道,基本上使用Single Conversion Mode即可
大部分設定都不用動,維持預設
只要稍微留意一些參數即可 EOC Selection, Sampling Time
我們這邊只修改 Regular Channel 轉換觸發源
External Trigger Conversion Source: HRTimer Trigger Out 1 event
我們可以看到從時脈圖看到ADC Clock為72MHz
Step 5. NVIC 中斷設定
基本題中使用中斷來測量ADC轉換時間
思路大概是這樣
只要測量 PA4 HIGH 的時間就可以知道實際ADC轉換時間了
也可以先用手冊給的估算公式估算一下轉換時間
轉換時間 = 採樣時間 + 12.5 clock cycles
根據我們剛剛的設定,Sampling Time 是 1.5 cycle
ADC clock = 72 MHz,所以 T_cycle = 1 / 72M = 14 (ns / cycle)
Cycle_conv = 1.5 + 12.5 = 14 (cycle)
T_conv = 14 cycle * 14 ns / cycle = 196 ns
轉換時間大約會在196 ns 左右
好的,我們可以來設定 NVIC 中斷了
勾選
ADC1 and ADC2 interrupts
HRTIM master global interrupts
即可,其餘不用再做設定
Step 6. 改用LL庫
Step 7. 大膽 Generate Code吧
提供 ioc檔與設定報告供大家參考核對設定
- ioc檔https://drive.google.com/file/d/1aIMNGufgrGj8r0qZGsFcsuHQaNkrwy95/view?usp=sharing
- 設定報告( pdf )
https://drive.google.com/file/d/18ofhHn2YeyVbPZ4Tbkyv3vxyQH6AOqUT/view?usp=sharing
Section 1.4 程式碼撰寫
main.c
這裡宣告一個全域變數用來監看值
區域變數無法即時查看
只能透過Break Point在對應區塊暫停程式才能看到
記得啟用HRTIM的Counter
還有啟用對應的中斷函數
啟用ADC模組與啟動ADC轉換
中間要等待ADC自動校正
最後while中提供讀取ADC值的兩種方式給大家參考
stm32f3xx_it.c
中斷函數裡面全部使用暫存器寫法是為了拚效能
同學可試試看不使用暫存器寫法會出現什麼樣的不同
Section 1.5 實驗結果
運行中將 PA0 接到 3.3V,可看到值很接近 4095
測量 PA4 可看到 ADC 觸發頻率為100kHz,符合題目要求
最後是轉換時間測試
筆者測試結果為196ns,與理論計算結果一致
因為筆者做這題測試還做了一些特殊處理
同學們做出來的不會是這個數字,轉換時間肯定更久
甚至根據中斷函數中使用不同的語法會出現250~980ns的轉換時間
這邊留個作業給大家
為甚麼單純用以上方法測量會會比 196ns 還久?
該如何解決這個問題?
提示: 跟筆者標示粗體的部分相關
解決方案
Section 2. 進階題
將ADC1_IN1(PA0)腳位設定為一般通道,輸入0~3V電壓,
使用HRTIM之Timer A模組,輸出PWM,
設定互補模式且Duty cycle = 50%,Deadtime = 1us,
並使用HRTIM之Timer Master作為ADC觸發源,
且開啟Timer Master中斷函數,並在中斷函數中施作以下判斷式:
A. 若輸入電壓為 0~1V, Frequency of Timer A = 80kHz
B. 若輸入電壓為 1~2V, Frequency of Timer A = 100kHz
C. 若輸入電壓為 2~3V, Frequency of Timer A = 120kHz
而ADC觸發頻率(即Timer Master中斷頻率)隨Timer A頻率變化。
提供更改頻率的函數給大家參考
LL_HRTIM_TIM_SetPeriod (HRTIMx, Timerx, Period);
或暫存器寫法:
HRTIM1->sMasterRegs.MPER = Period; //for Timer Master
HRTIM1->sTimerxRegs[x].PERxR = Period; //for others
本題可開啟半波模式,他會自動計算50% Duty所需比較器值
就不用更新比較器了
只需先 Enable Compare Unit 1
再Enable Half Mode 即可,順序不可顛倒
Section 2.1 程式碼撰寫
按照基本題與Lesson 3.內容做本題設定即可
提供 ioc檔與設定報告供大家參考核對設定
- ioc檔https://drive.google.com/file/d/1aIMNGufgrGj8r0qZGsFcsuHQaNkrwy95/view?usp=sharing
- 設定報告( pdf )
https://drive.google.com/file/d/18ofhHn2YeyVbPZ4Tbkyv3vxyQH6AOqUT/view?usp=sharing
main.c
本題要求寫在中斷函數中
所以int main() 的 while迴圈保持空白