在本次項目中,限於空間要求我們選用了STM32F030F4作為控制芯片。這款MCU不但封裝緊湊,而且自帶的Flash空間也非常有限,所以我們選擇了LL庫實現。本文我們將說明如何通過LL庫實現PWM信號的輸出。
1、概述
我們知道STM32的TIM計時器可以輸出PWM信號,這測我們也采用STM32F030F4中的TIM3通用計時器來實現我們想要的功能。TIM3通用計時器由一個16位的自動重新加載計數器組成,由一個可編程的預定標器驅動。其結構如下圖所示:

它可以用於各種目的,包括測量輸入信號的脈沖長度(輸入捕獲)或生成輸出波形(輸出比較和PWM)。使用定時器預標量和RCC時鍾控制器預標量,輸出的PWM脈沖長度和波形周期可以調整從幾微秒到幾毫秒。我們這里實現一個占空比0%到100%可調,頻率為200Hz的PWM波形。
2、TIM配置
我們在使用TIM3輸出PWM波,我們必須對其進行相應的配置。關於TIM3的配置我們需要關注:TIM3控制寄存器1 (TIM3_CR1)、TIM3預置寄存器(TIM3_PSC)、TIM3自動重載寄存器(TIM3_ARR)以及對應通道的捕獲比較寄存器。
首先來看一看TIM3控制寄存器1 (TIM3_CR1),這個寄存器用於配置TIM計時器。其結構如下:

對於TIM3控制寄存器1 (TIM3_CR1)我們主要需要說一下計數器使能(CEN)位。而其它的位通過初始化函數設置就可以了。
TIM3預置寄存器(TIM3_PSC)用以配置TIM計數器的工作頻率,這個工作頻率的計算是:psc的工作頻率/(psc的值+1)。其結構如下:

TIM3自動重載寄存器(TIM3_ARR)用以配置輸出PWM波的頻率或者說周期。因為這個值就是計數器的計數周期。其結構如下:

我們設置了技術器的時鍾頻率,計數的周期,要想得到PWM波,我們還需要告訴TIM一個占空比。關於占空比實際上是在捕獲比較寄存器中設置的。
3、PWM實現
我們已經如何通過配置TIM得到PWM波形輸出,我們接下來就是通過軟件來實現我們的想法。其配置代碼如下:
/* TIM3 初始化配置 */
static void TIM3_Init_Configuration(void)
{
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* TIM3時鍾使能 */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/* TIM3初始化配置 */
TIM_InitStruct.Prescaler = 47;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = TIMPERIOD;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH4);
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.CompareValue = 0;
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct);
LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH4);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
/* TIM使用GPIO時鍾使能 */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
/* TIM3 GPIO配置:PB1 ------> TIM3_CH4 */
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LL_TIM_CC_EnableChannel(TIM3,LL_TIM_CHANNEL_CH4);
LL_TIM_EnableCounter(TIM3);
}
在這段配置代碼中,有幾個值需要說一下。Prescaler 值我們設為47,所以在48MHz的系統時鍾下,TIM計數器的工作頻率就是1MHz。Autoreload 的值我們設為了5000,所以可以得到PWM的頻率為200Hz。CompareValue值設為了0,所以我們只能得到占空比為0%的PWM。若我們想要得到占空比為50%的PWM,則CompareValue值應設為2500才行。配置完成后各寄存器的值如下圖所示:

這要得到的只是固定占空比的PWM波,若想動態修改占空比則需要修改捕獲比較寄存器的值。使用函數LL_TIM_OC_SetCompareCH4(TIM3,pulse)就可以了,其中pulse是處於0到Autoreload 的值的整數。
4、總結
我們通過上述操作,就實現了基於LL庫的PWM波的輸出。我們將代碼下載到目標板,並修改占空比和監視器波形輸出。

上圖是占空比為50%的波形圖。

上圖是占空比為20%的波形圖。

上圖是占空比為80%的波形圖。
歡迎關注:

