一,何爲PWM?
PWM的全稱爲:Pulse Width Modulation,簡稱脈寬調製
百度來的:脈衝寬度調製是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術。
而簡單的來說就是,我們可以使用處理器輸出自己想要的佔空比的矩形波,去達到控制模擬電路等目的。
二,STM32中擁有PWM
在STM32F407的芯片手冊中有描述:12個16位的定時器,2個32位的定時器,每個定時器可以由4個通道去產生PWM
三,STM32中的PWM的原理
先說PWM的關鍵指標:週期,以及佔空比
1.PWM週期:就是通過配置定時器的溢出時間(即圖中ARR的值),當計數器(CNT寄存器)計數的值與ARR的值相等時,計數歸零,重新計數
2.PWM佔空比:設置CRRx的值,作爲比較值,CNT計數值與CRR做對比,因此衍生出PWM的模式,
如:在PWM模式1,當計數器CNT<CRR,輸出通道設置的輸出電平爲有效電平,否則爲無效電平
上圖就是設置輸出通道極性爲低,CRRx爲150,ARR爲500 可以看到當小於150時表現出來的爲低電平,否則就是爲高電平。
四.PWM的配置流程如下
1.使能GPIO時鐘,配置一個GPIO結構體變量(該GPIO上可以複用爲定時器的輸出),並進行初始化
2.將GPIO的引腳複用爲TIM的輸出
3.使能定時器時鐘,配置一個TIM結構體變量,主要關注設置Arr的值,並進行初始化
4.配置TIM_OCInitTypeDef結構體,用於輸出比較的結構體,
/**
* @brief TIM Output Compare Init structure definition
*/
typedef struct
{
uint16_t TIM_OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint16_t TIM_OutputState; /*!< Specifies the TIM Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_State */
uint16_t TIM_OutputNState; /*!< Specifies the TIM complementary Output Compare state.
This parameter can be a value of @ref TIM_Output_Compare_N_State
@note This parameter is valid only for TIM1 and TIM8. */
uint32_t TIM_Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between 0x0000 and 0xFFFF */
uint16_t TIM_OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint16_t TIM_OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
uint16_t TIM_OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;
主要注意一下幾樣:
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //PWM的輸出模式
TIM_OCInitStructure.TIM_OutputState=ENABLE; //使能
TIM_OCInitStructure.TIM_Pulse=250; //脈衝,即與CNT比較的數值
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //輸出極性,與PWM模式配合,產生最後的輸出
TIM_OC1Init(TIM14,&TIM_OCInitStructure);
因此最後還要再調用兩個函數
TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM14,ENABLE);
最後實現PWM的初始化代碼如下:
/**
* @brief the TIM14 used to produce a PWM
* @param arr: TIM重裝載計數值
* @param psc: 分頻係數
* @param pluse:初始化佔空比設置
* TIM_SetCompare1() ¸該函數可以動態改變佔空比的值
* @retval None
*/
void INIT_PWM(int arr,int psc,int pluse)
{
//使能GPIOF的外設時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//聲明一個GPIO結構體變量
GPIO_InitTypeDef GPIO_InitStructure;
//定義一個GPIO結構體變量
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; // LED所在的IO口,定時器14
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //複用
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //100MHz的時鐘
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推輓
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉
//初始化GPIOF
GPIO_Init(GPIOF,&GPIO_InitStructure);
/將GPIO複用至TIM14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
//使能定時器14的外設時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
//聲明一個定時器結構體變量
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_Period=499; //Tout=(ARR+1)(PSC+1)/Tclk (499+1)(83+1)/(84M)=500*(1us)=500us
TIM_TimeBaseInitStructure.TIM_Prescaler=83;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
//³õʼ»¯¶¨Ê±Æ÷14
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStructure);
//PWMÉèÖÃ
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //PWM1模式
TIM_OCInitStructure.TIM_OutputState=ENABLE; //使能至輸出引腳
TIM_OCInitStructure.TIM_Pulse=250; //加載值CCR中的值
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //輸出的極性
TIM_OC1Init(TIM14,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_Enable); //比較其重裝載
TIM_ARRPreloadConfig(TIM14,ENABLE); //使能定時器的重裝載
//使能定時器14
TIM_Cmd(TIM14,ENABLE);
}
最後若要想動態的改變佔空比,就要在主函數中調用以下函數來設置:
TIM_SetCompare1(TIM14,pwmval);