脈沖寬度調(diào)制(PWM)翅敌,是英文“Pulse Width Modulation”的縮寫羞福,簡稱脈寬調(diào)制,是利用微處理器的數(shù)字輸出來對模擬電路進行控制的一種非常有效的技術(shù)蚯涮。簡單一點治专,就是對脈沖寬度的控制。調(diào)整PWM的周期遭顶、PWM的占空比而達到控制充電電流的目的.
老規(guī)矩张峰,先讓我們來看pwm.c中的源碼:
#include "pwm.h"
#include "led.h"
//PWM輸出初始化
//arr:自動重裝值
//psc:時鐘預分頻數(shù)
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO外設(shè)時鐘使能
//設(shè)置該引腳為復用輸出功能,輸出TIM,CH1的PWM脈沖波形
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_8; //TIM_CH1
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP; //復用推挽輸出
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period=arr;//設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler=psc;//設(shè)置用來作為TIMx時鐘頻率除數(shù)的預分頻值 不分頻
TIM_TimeBaseStructure.TIM_ClockDivision= 0; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM2; //選擇定時器模式:TIM脈沖寬度調(diào)制模式2
TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_Pulse= 0; //設(shè)置待裝入捕獲比較寄存器的脈沖值
TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC1Init(TIM1,&TIM_OCInitStructure); //根據(jù)TIM_OCInitStruct中指定的參數(shù)初始化外設(shè)TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主輸出使能
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //CH1預裝載使能
TIM_ARRPreloadConfig(TIM1,ENABLE); //使能TIMx在ARR上的預裝載寄存器
TIM_Cmd(TIM1,ENABLE); //使能TIM1
}
這里我們要配置PA8為復用輸出棒旗,這是因為TIM1_CH1通道將使用PA8的復用功能作為輸出挟炬。
首先,我要介紹一下占空比:
占空比是PWM的最重要的參數(shù)
8位的PWM是0-255(2^8)嗦哆,比如用PWM控制一個電源正極的開關(guān)當PWM頻率足夠高的時候,開關(guān)后的電壓是 = 電壓占空比比如你用5V電源婿滓,用一個MOS管控制電源輸出的話給MOS管30%的占空比老速,那么就是輸出5V30%的電壓
然后再說說怎么實現(xiàn)這個占空比。8位的定時器凸主,如果做PWM橘券,要輸出30%的占空比,那么定時器從0~255*30%的計數(shù)值內(nèi)(也就是76內(nèi))要輸出高電平卿吐。然后比較當前的計數(shù)值跟76旁舰,計數(shù)值小于76就輸出高電平,大于76的時候就輸出低電平嗡官。
再讓我們來看一下TIM_TimeBaseStructure這個結(jié)構(gòu)體的各個成員
typedef struct
{
uint16_t TIM_OCMode;
uint16_tTIM_OutputState;
uint16_t TIM_OutputNState;*/
uint16_tTIM_Pulse;
uint16_tTIM_OCPolarity;
uint16_tTIM_OCNPolarity;
uint16_tTIM_OCIdleState;
uint16_tTIM_OCNIdleState;
}TIM_OCInitTypeDef;
參數(shù)TIM_OCMode設(shè)置模式是PWM還是輸出比較箭窜,這里我們是PWM模式。(PWM有兩種模式衍腥,一種是向上計數(shù)磺樱,一種是向下計數(shù))
參數(shù)TIM_OutputState用來設(shè)置比較輸出使能纳猫,也就是使能PWM輸出到端口。(用計數(shù)值和用占空比計算得到的數(shù)進行比較竹捉,這里用上面提到的76舉例芜辕,就是比較計數(shù)值與76的大小,根據(jù)下面TIM_OCPolarity定義的值判斷块差,大于76時輸出高電平還是小于76時輸出低電平侵续,所以使能輸出比較結(jié)果,就是允許輸出PWM)
參數(shù)TIM_OCPolarity用來設(shè)置極性是高還是低憨闰。(取值為TIM_OCPolarity_High時状蜗,計數(shù)值比76小時定義為高電平,比76大時定義為低電平起趾,取值為TIM1_OCPolarity_Low時相反)
其他參數(shù) TIM_OutputNState 诗舰,TIM_OCNPolarity , TIM_OCIdleState 和 TIM_OCNIdleState 是高級定時器TIM1和TIM8才用到的训裆。
這里我們只要使用通用定時器的功能眶根,所以沒有必要初始化這些成員。
配置好了之后用TIM_OC1Init(TIM1,&OCInitStructure)函數(shù)初始化TIM1 OC1;
如果是高級定時器边琉,則還需要配置:剎車和死區(qū)寄存器(TIMx_BDTR)属百,該寄存器,我們只需要關(guān)注最高位:MOE位变姨,要想高級定時器的PWM正常輸出族扰,則必須設(shè)置MOE位為1,否則不會有輸出定欧。注意:通用定時器不需要配置這個渔呵。其他位我們這里就不多說。
接下來的三個使能還是要看定時器結(jié)構(gòu)的
如上圖砍鸠,這里我就不多說了扩氢。
最后我要解釋一下關(guān)于為什么LED是漸變的,雖然TIM1計數(shù)器中的計數(shù)值要與76比較爷辱,但是這一個周期的時間十分短暫录豺,導致低電平時間過短,達到人眼無法分辨的頻率饭弓,所以我們覺得LED一直是亮著的双饥,這個時候決定LED變化的只有主函數(shù)中最后一段代碼中的函數(shù)TIM_SetCompare1(TIM1,led0pwmval)中的led0pwmval這個參數(shù)決定的占空比,從而影響電壓進而影響電流大小弟断,最后導致了LED的亮度的改變咏花。