前言
在之前的內容中已經介紹過基本的 Timer 用法,及 PWM 的計算。
在使用 PWM 時我們會需要控制兩種參數:頻率與 Duty Cycle(佔空比)。頻率的部分和 Timer 一樣,由 TIMx_PSC 與 TIMx_ARR 暫存器的值來設定,而 Duty Cycle 則由 TIMx_CCRx 暫存器來指定。
這篇的目標是寫出一個可以設定 PWM 頻率與 Duty Cycle 的程式,並讓 STM32 輸出 PWM 訊號。
正文
首先一樣以 Nucleo-F446RE 做示範。
首先建立一個 PIO 的專案,選擇 Framework 為「libopencm3」,並在 src/
資料夾中新增並開啓 main.c
檔案。
完整程式
分段說明
Include
和 Timer 時相比只少了中斷的 nvic.h
,要使用 PWM 就只需要這 3 個功能就可以了。
計算並設計 Timer 參數(PSC、ARR、CCR 暫存器)
這部分的 PWM_TIMER_CLOCK
、PWM_COUNTER_CLOCK
、PWM_TIMER_PRESCALER
(PSC)、 PWM_TIMER_PERIOD
(ARR) 和 Timer 的部分一樣,就不再贅述。
這次的重點是 CCR 暫存器。在上一篇中已經說明其關係式為:
Duty_Cycle% = CCR / (ARR + 1) * 100%
所以
CCR = (ARR + 1) * Duty_Cycle% / 100%
因此這裡以 PWM_TIMER_OC_VALUE
為名定義 CCR 的計算公式 (PWM_TIMER_PERIOD + 1) * PWM_GOAL_DUTY_CYCLE / 100
。
RCC
這部分還是和 Timer 一樣。重點一樣是指定時鐘源為 8 MHz 的 HSE,並設定系統時鐘為 168 MHz。
PWM 與 Timer 設定
要使 GPIO 可以輸出 PWM 訊號的話,要將 Timer 的 Channel 對應的 GPIO 設定為 Alternate function。我們使用 TIM3 的 Channel 2。
Timer 大部分的設定都和和上一篇的一樣,主要差異為要使用 timer_set_oc_mode()
指定使用 Channel 2(TIM_OC2
),並設定為 TIM_OCM_PWM1
模式。
使用 timer_set_oc_value()
函式將 CCR 的值傳給 TIMx_CCRx 暫存器。
多環境程式(F446RE + F103RB)
由於 STM32F1 的部分函式不同,所以 F103RB 沒辦法直接使用上面的 F446RE 的程式。
以下列出主要的差異部分,也就是 RCC 與 GPIO 的部分。完整的程式請看 GitHub repo。
成果
我使用兩組開發板並分別設定為頻率 1kHz
, Duty Cycle 72.5%
以及頻率 2kHz
, Duty Cycle 15.0%
。
可以看到 PWM 的輸出結果是相當精準的。
小結
這次介紹了 STM32 的 PWM 用法,PWM 是 Timer 的延伸功能,因此大部分的設定都和 Timer 有關,如果 Timer 有理解的話 PWM 應該不會太難。
參考資料
本文的程式也有放在 GitHub 上。
本文同步發表於 iT 邦幫忙-2022 iThome 鐵人賽。
留言可能不會立即顯示。若過了幾天仍未出現,請 Email 聯繫:)