STM32筆記(22):PWM基本概念與呼吸燈(上)

本篇將繼續使用 Timer 的功能來呈現 PWM 的效果。所謂的 PWM (Pulse Width Modulation),是將類比訊號轉換為脈波的一種技術,先前的文章,已經提到使用 PWM 控制伺服馬達的應用,使用 Arduino IDE 的介透過 STM32 進行控制:STM32F103x STM32筆記(6):使用可變電阻控制MG90S伺服馬達 本篇文章將使用 STM32 的標準函式庫來撰寫 PWM 程式,控制馬達、燈光等。

PWM 的應用非常廣泛,常見的如燈光的亮度、馬達的轉速等,都是運用 PWM 的技術來達成。PWM 的應用控制屬性,主要是信號的頻率、佔空比及分辨率。本篇實做將運用 PWM 的方法,撰寫一個簡單的應用程序來製作 LED 呼吸燈。

[關於呼吸燈]

談到 PWM 就一定要知道「佔空比(Duty Cycle)」,例如 LED 1 秒鐘內,高低電位各佔 0.5 秒,這時的頻率是 1 Hz,佔空比為 50%,LED 看起來會閃爍,如果頻率改成 100Hz,也就是在 10 毫秒時間內,5 毫秒高電位,5毫秒低電位,這時佔空比仍為 50%。這時看到的 LED 是恆亮的,原因是來不及熄滅又亮起來,但是亮度會比較暗,高電位的供電時間僅 50%,跟原先的亮度比較起來只有 50%。佔空比越大,亮的時間就越長,視覺上也就越亮。

要持續看到 LED 發亮,其刷新頻率大於 50Hz(每秒 50次)的時候,眼睛就會產生視覺暫留效果,看起來是一個恆亮的 LED 燈,如果頻率低於 50 太多的話,看起來就會閃爍。

所以,在頻率可造成視覺暫留的情況下,可以用不同佔空比改變 LED 燈的亮度。使其達到一個呼吸燈的效果。結論如下:「頻率高時,不會閃爍,頻率低時,容易閃爍,兩種情況下佔空比越大,LED 就越亮。」

[PWM ]

STM32筆記(19):定時器 Timer 與定時器中斷 文中提到 STM32 的通用定時器包括 TIM2、TIM3、TIM4、TIM5,每個定時器都有獨立的 4 個通道可以用來作為:輸入捕獲、輸出比較、PWM輸出、單脈衝模式輸出等。用以下通用定時器的方塊圖說明比較容易瞭解。我們將通用計時器分為四個部分:(英文名稱後面的英文版參考手冊的章節,如果是中文版在第 14 章)

① 選擇時鐘 Clock selection (15.3.3)
② 時基電路 Time-base unit (15.3.1)
③ 輸入捕獲 Input capture mode (15.3.5)
④ 輸出比較 Output compare mode (15.3.8)

定時器除了 TIM6 和 TIM7(基本定時器)之外,其他的定時器都可以產生 PWM 輸出,高級定時器 TIM1、TIM8 可以同時產生 7 路 PWM 輸出,而通用定時器可以同時產生 4 路 PWM 輸出通道,每一個通道都有一個捕獲比較暫存器,將暫存器值和計數器值比較,透過比較結果輸出高低電位,實現 PWM 信號。
上圖 CNT 是計數器,ARR 為定時器重新裝載值,CCRx 是比較值,在 t 時刻將計時器跟 CCRx 進行比較,如果計數器值小於 CCRx 值,輸出低電位,如果計數器值大於 CCRx 值,輸出高電位。

計時器從 0 開始向上計數,當 t0~t1 時,計時器計數器 TIMx_CNT 值小於 CCRx 值,這時輸出為低電位,t1~t2 時,計時器計數器 TIMx_CNT 值大於 CCRx值,輸出高電位。當 TIMx_CNT 值達到 ARR 時,計時器溢位,時間為 t2 ,這時稱為 PWM 的一個週期,在繼續重新向上計數。

產生的波形稱為 PWM 信號,其頻率由內部時鐘、預分頻器和 ARRx 暫存器決定 PWM 週期(在時鐘頻率一定的情況下,當前為預設內部時鐘 CK_INT),CCRx 則決定 PWM 占空比(高低電平所占整個週期比例)。

PWM 並不總是必須遵循完全相同的 PWM 生成程序,但是,它是非常基本的,並且更容易理解這個概念。它被稱為向上計數PWM模式。我們將在本系列教程中繼續討論更高級的 PWM 生成技術。

再來看一下輸出階段的捕獲/比較頻道 1 放大的方塊圖:
① TIMx_CCMR1 暫存器的 OC1M[2:0] 位元,設置輸出模式控制器:其值為 110 時稱為 PWM 模式1,其值為 111 時稱做 PWM 模式2。
② 計數器值 TIMx_CNT 與通道1 捕獲比較暫存器 CCR1 進行比較,通過比較結果輸出有效電位和無效電位,OC1REF = 0 時為「無效低電位」,OC1REF = 1 時為「有效高電位」。
③ 透過輸出模式控制器產生的信號 TIMx_CCER 暫存器的 CC1P 位,設置輸入/捕獲通道1 輸出極性,CC1P = 0 時為高電位有效,CC1P = 1時為低電位有效。
④ TIMx_CCER:CC1E 位元控制輸出啟用電路,信號由此輸出到對應引腳,0:關閉,1:開啟 。

在整理上面這段時,一直搞不清楚 CC1P、OC1 之間的關係,整理成下表會比較容易理解:
OC1REFCC1P功能OC1描述
00OC1高電位有效0 (低電位)無效
01OC1低電位有效1 (高電位)無效
10OC1高電位有效1 (高電位)有效
11OC1低電位有效0 (低電位)有效


[常用的 PWM 函式]

void TIM_OCxInit(TIM_TypeDef *TIMx, TIM_OCInitTypeDef *TIM_OCInitStruct)
PWM 通道設置是通過函式(函式名稱的x 需改成 1~4 其中一個數字) TIM_OC1Init()~TIM_OC4Init()來設置的,不同的通道的設置函數不一樣,使用的是通道 1,就使用的函數是 TIM_OC1Init()。
輸出比較結構體 TIM_OCInitTypeDef 用於輸出比較模式,與 TIM_OCxInit 函數配合使用完成指定定時器輸出通道初始化配置。通用定時器有四個定時器通道,使用時都必須單獨設置。
- 引數 TIMx ,x 可以是 1 到 17,除了 6 和 7 以外的 TIM 外設。

對 TIMx 進行初始化,需先定義並填入一個 TIM_OCInitTypeDef 類型的結構體。
TIM_OCInitTypeDef TIM_OCInitStructure;		//定義結構體
TIM_OCInitStructure 這個結構體有以下 5 個引數:
引數名稱說明
TIM_OCInitStructure.TIM_OCMode = xxx;選擇定時器模式,xxx 常用的:
TIM_OCMode_Timing
TIM_OCMode_Active
TIM_OCMode_Inactive
TIM_OCMode_Toggle
TIM_OCMode_PWM1
TIM_OCMode_PWM2
TIM_OCInitStructure.TIM_OutputState = xxx;決定最終的輸出比較信號 OCx 是否通過外部引腳輸出。xxx 可以是以下值:
TIM_OutputState_Disable
TIM_OutputState_Enable
TIM_OCInitStructure.TIM_OCPolarity = xxx;指定輸出極性,當計時器計數值小於 CCR1_Val 時為低電平,xxx 可以是以下值:TIM_OCPolarity_High
TIM_OCPolarity_Low
TIM_OCInitStructure.TIM_Pulse = n;設置初始 PWM 脈衝寬度,實際上就是配置占空比(捕獲比較暫存器1,CCR1),n 可設定範圍從 0 至 65535。

void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
(函式名稱的x 需改成 1~4 其中一個數字)啟用或禁用 CCRx 上的 TIMx 外設預載暫存器。
- 引數 TIMx ,x 可以是 1 到 17,除了 6 和 7 以外的 TIM 外設。
- 引數 TIM_OCPreload 設定為啟用TIM_OCPreload_Enable 或 TIM_OCPreload_Disable。

void TIM_SetCompare1(TIM_TypeDef *TIMx, uint16_t Compare1)
設定 TIMx 捕獲比對暫存器的值。用來更改 CCR 暫存器的函式,
- 引數 TIMx 的 x 可以是 1 to 17,除了6 和 7 以外。
- 引數 Compare1 是用於與 TIMx 比較的數,相當於用 TIMx 的一個週期的時間減去這個 Compare1,使得 TIMx 的周期從後面開始的Compare1 的時間為 TIMx 的前部分時間的反向。即若前部分時間為高電平,則 Compare1 段所在時間為低電平。若前部分時間為低電平,則Compare1段所在時間為高電平。

下一篇:STM32筆記 (22):PWM基本概念與呼吸燈(下)

Post a Comment

較新的 較舊