STM32 PWM輸出

文將介紹經過STM32的定時器輸出PWM,若是對定時器不太熟悉的同窗能夠看下以前的文章《STM32基礎定時器詳解》,關於定時器的基礎功能再也不詳解。git

0一、PWM介紹

PWM定義:脈衝寬度調製(PulseWidthModulation,PWM)簡稱脈寬調製。通俗講,PWM是一種對模擬信號電平進行數字編碼的方法。經過高分辨率計數器的使用,方波的佔空比被調製用來對一個具體模擬信號的電平進行編碼。PWM信號仍然是數字的,由於在給定的任什麼時候刻,滿幅值的直流供電要麼徹底有(ON),要麼徹底無(OFF)。電壓或電流源是以一種通(ON)或斷(OFF)的重複脈衝序列被加到模擬負載上去的。通的時候便是直流供電被加到負載上的時候,斷的時候便是供電被斷開的時候。只要帶寬足夠,任何模擬值均可以使用PWM進行編碼。github

佔空比定義:佔空比就是高電平所佔整個週期的時間,以下圖所示:app

第一個PWM波,週期爲10ms,高電平的時間爲4ms,因此佔空比爲40%,同理第二個PWM波爲60%,第三個爲80%。ui

PWM的頻率: PWM的頻率的整個週期的倒數,因此說上圖PWM的週期爲1/0.01,也就是100HZ。改變PWM的頻率是經過改變整個的週期實現的。因此經過改變高低電平總共的時間、改變高電平佔總週期的比例就能夠實現任意頻率、任意佔空比的PWM波。編碼

PWM的用途和優勢:電機調速、功率調製、PID調節、通訊等等,配置簡單、抗干擾能力強,從處理器到被控系統信號都是數字形式的,無需進行數模轉換。而且讓信號保持爲數字形式可將噪聲影響降到最小,噪聲只有在強到足以將邏輯1改變爲邏輯0或將邏輯0改變爲邏輯1時,也才能對數字信號產生影響,這是PWM用於通訊的主要緣由。spa

0二、STM32的管腳複用

STM32沒有專門的PWM引腳,因此使用IO口的複用模式。首先確認PWM功能的輸出管腳,使用定時器9。從下面的框圖中得知,timer9只有兩個輸出通道,因此timer9只能輸出兩路PWM。3d

在STM32F207數據手冊中的Alternatefunction mapping圖片中,timer9的兩個通道分別能夠複用爲PA2,PA3,PE5和PE6。code

0三、STM32輸出PWM原理

下圖中的①部分,在《STM32基礎定時器詳解》講解過了,關於影子寄存器,也在《STM32影子寄存器》中講述,下文再也不贅述了。本文將重點在②部分,捕獲/對比通道講解,其中STM32的PWM就是利用對比通道實現的。blog

Pulse Width Modulation mode allows you to generate a signal with afrequency determined by the value of the TIMx_ARR register and a dutycycle determined by the value of the TIMx_CCRx register。教程

節選自STM32F207 Reference manual手冊

脈衝寬度調製模式能夠生成一個信號,該信號頻率由TIMx_ARR 寄存器值決定,其佔空比則由TIMx_CCRx 寄存器值決定。

從下圖能夠看出,當CCR寄存器和CNT計數器數值同樣時,會產生動做(改變通道對應的GPIO電平)。因爲CNT溢出時,重載值由TIMx_ARR寄存器值決定的。因此說TIMx_ARR寄存器值決定週期,而TIMx_CCRx寄存器值決定CNT溢出時,通過多久會產生動做(改變通道對應的GPIO電平),也就是決定了佔空比。

以向上計數爲例,重載值爲ARR,比較值爲CRRx

上圖能夠看出:

  1. 0-t1段,定時器計數器TIMx_CNT值小於CCRx值,輸出低電平。

  2. t1-t2段,定時器計數器TIMx_CNT值大於CCRx值,輸出高電平。

當TIMx_CNT值達到ARR時,定時器溢出,從新向上計數...循環此過程至此一個PWM週期完成。

 

上圖更加形象的說明了

  1. 信號頻率由 TIMx_ARR 寄存器值決定。

  2. 佔空比則由 TIMx_CCRx 寄存器值決定。

 

STM32輸出PWM的過程:

一、首先配置GPIO,配置定時器,具體參考一下代碼。定時器配置參考《STM32基礎定時器詳解》。

二、捕獲/比較通道使能比較通道。

上圖看到,①寄存器名字爲:Capture/Compare1register。能夠選擇從②處輸入捕獲,也能夠選擇從從③中輸出,也就是咱們須要的PWM輸出功能。選擇捕獲通道,仍是選擇比較通道,在框圖中沒有找到具體的說明,但在TIMx_CCMR1寄存器CC1S[1:0]控制位使能。

三、使能完輸出,就要配置PWM輸出了

①TIMx_CCMR1寄存器的OC1M[2:0]位,設置輸出模式控制器

110:PWM模式1,111:PWM模式2。

②計數器值TIMx_CNT與通道1捕獲比較寄存器CCR1進行比較,經過比較結果輸出有效電平和無效電平。

OC1REF=0 無效電平,OC1REF=1無效電平。

③經過輸出模式控制器產生的信號。TIMx_CCER寄存器的CC1P位,設置輸入/捕獲通道1輸出極性。

0:高電平有效,1:低電平有效。

④TIMx_CCER:CC1E位控制輸出使能電路,信號由此輸出到對應引腳。

0:關閉,1:打開。

 

首先對PWM模式1和PWM模式2進行介紹:

模式1

在向上計數時,一旦TIMx_CNT<TIMx_CCR1時通道1爲有效電平,不然爲無效電平;在向上計數時,一旦TIMx_CNT>TIMx_CCR1時通道1爲無效電平(OC1REF=0),不然爲有效電平(OC1REF=1)。

模式2

在向上計數時,一旦TIMx_CNT<TIMx_CCR1時通道1爲無效電平,不然爲有效電平;在向下計數時,一旦TIMx_CNT>TIMx_CCR1時通道1爲有效電平,不然爲無效電平。

TIMx_CNT>TIMx_CCR1時通道1爲有效電平,不然爲無效電平。

PWM輸出高低電平由TIMx_CCMR1:OC1M位和TIMx_CCER:CC1P位共同決定。


總結下來:

模式1:

    CNT<CCR爲有效電平//(OC1REF =1)

    CNT>CCR爲無效電平//(OC1REF =0)

模式2:

    CNT<CCR爲無效電平//(OC1REF =0)

    CNT>CCR爲有效電平//(OC1REF =1)

CC1P:

    0:高電平有效

    1:低電平有效


0四、STM32輸出PWM配置

分析了原理,那麼下面就分析STM32生成PWM的過程。

一、首先要將GPIO設置爲複用輸出

/* GPIOE clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
  
/* GPIOE Configuration: TIM9 CH2 (PE6)*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOE, &GPIO_InitStructure); 
 
/* Connect TIM9 pins to AF3 */  
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_TIM9);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_TIM9);

二、配置定時器向上計數,配置定時器頻率

/* TIM9 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
 
/* Compute the prescaler value */
PrescalerValue = (uint16_t) ((SystemCoreClock) / 2000000) - 1;
 
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 1000-1;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);

三、配置PWM輸出

上面分析過程較爲麻煩,ST提供了標準外設庫,咱們只須要配置TIM_OCInitTypeDef結構體便可。

TIM_OCInitTypeDef  TIM_OCInitStructure;
 
/* PWM Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 100-1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
 
TIM_OC1Init(TIM9, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);

TIM_OCInitTypeDef結構體解析

typedef struct
{
  uint16_t TIM_OCMode;      //PWM模式1或者模式2
  uint16_t TIM_OutputState; // 輸出使能OR失能
  uint16_t TIM_OutputNState;  // PWM輸出不須要
  uint32_t TIM_Pulse; // 比較值
  uint16_t TIM_OCPolarity;// 比較輸出極性
  uint16_t TIM_OCNPolarity;   // PWM輸出不須要
  uint16_t TIM_OCIdleState;// PWM輸出不須要
 uint16_t TIM_OCNIdleState; // PWM輸出不須要
}TIM_OCInitTypeDef;

其中TIM_Pulse能夠在初始化時設置,設置完畢後,也能夠經過如下接口再次更新。

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1)

四、使能定時器

TIM_ARRPreloadConfig(TIM9, ENABLE);
 
/* TIM9 enable counter */
TIM_Cmd(TIM9, ENABLE);

使用timer9輸出PWM的波形

 

Keil和IAR工程代碼開源地址:

https://github.com/strongercjd/STM32F207VCT6

 

點擊查看本文所在的專輯,STM32F207教程

相關文章
相關標籤/搜索