一、什麼是PWM脈衝? PWM (Pulse Width Modulation) 脈衝寬度調製,通常應用於慣性系統中,(不是不能即停的設備,因為如果設備不具有關心,那麼運動是斷斷續續的,不具有連續性),通過脈寬調節輸出不同的波形作用域受控對象。 二、 PWM中三個重要的參數 1.頻率=1/Ts ;這 ...
一、什麼是PWM脈衝?
PWM (Pulse Width Modulation) 脈衝寬度調製,通常應用於慣性系統中,(不是不能即停的設備,因為如果設備不具有關心,那麼運動是斷斷續續的,不具有連續性),通過脈寬調節輸出不同的波形作用域受控對象。
二、 PWM中三個重要的參數
1.頻率=1/Ts ;這個很好理解,就是在單位時間內輸出的波形的個數啦。
2.占空比= Ton/Ts; 在一個脈衝周期內,脈衝波形中高電平的寬度占整個周期內波形寬度的比值。
3.解析度=占空比變化步距,指PWM最小能設定到的高電平時間所占周期的比例,也即最小占空比,意思就是把一個周期的時間分成了多少份,如果是10份,那麼占空比的精度就為10%。如果分成1000份,那麼占空比的精度就為0.1%。譬如頻率為600HZ的PWM,若最小能給到的時鐘是60kHZ,則解析度即為(1/60k)/(1/600)=1%。在同一個系統中,由於時鐘不變,提高頻率,則周期變小,解析度會變大。(前面的話可能不太好理解,那我就以自己的大白話給大家解說一下吧: 說白了其意思就是說把一個波形脈衝分成了多少分,例如解析度為0.1%,那就是把一個波形脈衝分割成了1000分,分別由不同份數的高低電平組個,例如占空比為50%d的脈衝,那就是有500份高電平,500份低電平,註意是連續的)
三、 PWM脈衝輸出配置(重點來啦)
事實上,需要輸出PWM脈衝,僅需要進行兩部分寄存器的配置,分別是時基單元(前面定時器中斷的時候已經詳細說過這裡不再贅述)、輸出比較單元的配置。首先看一下基本的結構如圖3所示。
定時器在不斷進行計數,其CNT不斷增大,(我這裡說的是向上計數),同在不斷的與CRR(使用者自己設定的值)寄存器的值進行比較,通過比較與CRR的值大小關係,與設定的模式進行工作,具體的模式如圖4所示。
本試驗使用的是PWM1 模式,計數的方式使用向上計數。其中計數從0到A點的工程中CNT<CRR,輸出有效電平(高電平),A點到B點過程中CNT>=RCC,輸出無效電平(低電平),這就完成了一個波形輸出,不斷的迴圈便能輸出一系列波形。
四、 具體程式
好了廢話不多說下麵我們一起來看看具體的代碼吧。這裡是輸出占空比 0---->100,100--->0不斷變化的的脈衝波,其頻率為1000HZ,解析度為1%.
CODE :PWM.c
#include"pwm.h"
void PwmInit(void)
{
//打開定時器時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //定時器2是通用定時器,其時鐘掛在到APB1時鐘線上
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE); //打開對應的GPIO的時鐘,註意這裡不同的外設可能掛載的時鐘不同,所以需要看原理圖,
GPIO_DeInit(GPIOA);// 註意這裡的函數非常的重要,這裡是將對應的GPIO埠初始化成預設的樣子,因為這個埠可能在以前使用過,其他的配置可能發生了改變
GPIO_InitTypeDef GPIOC_LED_PWM_Init; // 定義GPIO的結構體,也就是外設的結構體
GPIOC_LED_PWM_Init.GPIO_Pin= GPIO_Pin_0; // 配置需要使用的引腳
GPIOC_LED_PWM_Init.GPIO_Mode=GPIO_Mode_AF_PP; //配置引腳的輸出的模式,這裡使用大額CH1輸出波形,所以是復用模式
GPIOC_LED_PWM_Init.GPIO_Speed=GPIO_Speed_50MHz; // 配置輸出的頻率,這個在輸入的時候不需要配置
GPIO_Init(GPIOA ,&GPIOC_LED_PWM_Init); // 使用初始化函數初始化剛剛定義的結構體,以及對應的GPIO埠
//配置定時器2的時鐘源來自內部時鐘源,其實這裡系統預設的就是內部時鐘,所以這一步配置可以省去
TIM_InternalClockConfig(TIM2);
//定時器結構體配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ; //內部時鐘分頻
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100-1; //定時器溢出值
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1; //分頻繫數
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //這裡使用的是通用定時器沒有復用計數功能,這裡設置為0
//配置定時器2初始化
TIM_TimeBaseInit(TIM2 ,&TIM_TimeBaseInitStructure);
TIM_Cmd(TIM2,ENABLE); //使能定時器
//配置比較輸出單元
TIM_OCInitTypeDef PwmStruct;
TIM_OCStructInit(&PwmStruct); //給結構體賦初值,保證結構體中每一個變數都有初始值,防止使用高級定時器的時鐘時出現錯誤,應為通用定時器不具有某一個功能
PwmStruct.TIM_OCMode=TIM_OCMode_PWM1; // 輸出模式
PwmStruct.TIM_Pulse=0; //CCR
PwmStruct.TIM_OutputState=ENABLE; // PWM 輸出使能
PwmStruct.TIM_OCPolarity= TIM_OCPolarity_High;
TIM_OC1Init(TIM2,&PwmStruct);
}
//程式運行過程中設置不同的占空比
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2 ,Compare);
}
CODE :main.c
int main(){
Led_funcing();
PwmInit();
uint8_t i;
while(1)
{
for(i=0;i<=100;i++)
{
PWM_SetCompare1(i);
delay(100);
}
for(i=0;i<=100;i++)
{
PWM_SetCompare1(100-i);
delay(100);
}
}
}
有條件的寶寶可以使用LED燈 馬達自己模擬一下,我是用的是模擬模式輸出。
好啦,今天就給大家分享到這裡,如有錯誤和不合理的地方請大家指正。