stm32入門——PWM輸出控制直流電機變速
最近剛做了智能小車的尋迹實驗,實驗中用了定時器PWM輸出來改變直流電機的轉速,我在這裡就大緻總結一下PWM相關的知識。
什麼是PWM?
PWM(Pulse Width Modulation)脈沖寬度調制。
占空比:pwm占空比就是一個脈沖周期内有效電平在整個周期所占的比例。
通過調節PWM的占空比就能調節IO口上電壓的持續性變化,是以也能夠控制外設的功率進行持續性變化,也就能控制直流電機的轉速快慢。
那麼重點就在于如何調節PWM波形的輸出。如下圖所示

圖中的ARR是我們給定時器的一個預裝載值,CCRx的上下變化是産生PWM波的關鍵。我們假設ARR大于CCRx的部分輸出為高電平(即t1-t2、t3-t4、t5-t6),ARR小于CCRx的部分輸出為低電平(即0-t1、t2-t3、t4-t5),則改變CCRx的值就能改變輸出PWM的占空比。
隻要弄明白了上面那幅圖,那就不難了解想要控制PWM的輸出波形,重要的就是如何設定ARR與CCRx這兩個寄存器的值了。
PWM模式、有效電平
前面我們假設ARR大于CCRx時輸出為高電平,ARR小于CCRx時輸出為低電平,但在實際運用中可能并非如此,有可能是相反的情況——ARR大于CCRx時輸出為低電平,ARR小于CCRx時輸出為高電平,至于到底是哪種情況,還要看PWM是哪種模式、有效電平又設定的是何種極性了。
模式1:ARR小于CCRx時輸出為“有效”電平,ARR大于CCRx時輸出為“無效”電平。
模式2:ARR小于CCRx時輸出為“無效”電平,ARR大于CCRx時輸出為“有效”電平。
注意,我這裡用的是“有效”和“無效”,而不是“高”和“低”,也就是說有效電平可高可低,并非一定就是高電平。PWM模式、效電平極性,需要程式員自己配置相關的寄存器來實作。
以下面的代碼來講解
TIM1_PWM_Init(899,0);//不分頻。PWM頻率=72000/(899+1)=80Khz
我們使用定時器1的通道1來輸出一路PWM波,想詳細了解定時器參數的設定的朋友可以參考(stm32入門——定時器中斷),我這裡簡單介紹一下,這裡的899設定的就是ARR的值,至于那個0是用來設定TIM1的頻率的,不分頻就代表TIM1的時鐘頻率和系統時鐘相同,這裡假設為72MHz。
void TIM1_PWM_Init(u16 arr,u16 psc)
{
//此部分需手動修改IO口設定
RCC->APB2ENR|=1<<11; //TIM1時鐘使能
GPIOA->CRH&=0XFFFFFFF0; //PA8清除之前的設定
GPIOA->CRH|=0X0000000B; //複用功能輸出
TIM1->ARR=arr; //設定計數器自動重裝值
TIM1->PSC=psc; //預分頻器設定
TIM1->CCMR1|=7<<4; //CH1 PWM2模式
TIM1->CCMR1|=1<<3; //CH1預裝載使能
TIM1->CCER|=0<<1; //OC1 輸出使能
//TIM1->CCER|=1<<1;
TIM1->BDTR|=1<<15; //MOE 主輸出使能
TIM1->CR1=0x0080; //ARPE使能
TIM1->CR1|=0x01; //使能定時器1
}
前三行是用來配置GPIO口的,這裡不解釋。
TIM1->ARR=arr; //設定計數器自動重裝值
TIM1->PSC=psc; //預分頻器設定
這兩行就是我上門提到的設定定時器的頻率和重裝載值。
TIM1->CCMR1|=7<<4; //CH1 PWM2模式
TIM1->CCMR1|=1<<3; //CH1預裝載使能
TIM1->CCER|=0<<1; //OC1 輸出使能
這三行是用來設定PWM輸出模式和設定通道的,通道是什麼呢?簡單地講就是輸出PWM波的GPIO口,代碼一開始不是設定了PA8這個GPIO口嘛,這個PA8就是通道1。使用通道的話要先進行輸入輸出方向、通道使能的設定。
//TIM1->CCER|=1<<1;
這行我注釋掉的代碼,就是用來設定“有效電平”極性的,根據手冊,當TIM1->CCER[1]這位置1時,有效電平為低電平,置0時有效電平為高電平,而預設情況下置0。
TIM1->BDTR|=1<<15; //MOE 主輸出使能
這行代碼隻要對進階定時器進行設定,普通定時器無需設定。
TIM1->CR1=0x0080; //ARPE使能
這行代碼是用來使能ARPE,ARPE是什麼呢,就是當它被置1時,你自己設定的CCRx會立即生效,如果它被置為0,那麼你自己設定的CCRx值不會立即生效(可能之前ARPE已經有值了),而是當之前設定的CCRx生效後才會使用你最新設定的CCRx值。
上面的代碼裡沒有對CCRx進行設定,這是因為CCRx常常是一個變化的值,你可以在主函數中用一個for循環+if判斷語句對它進行++或–的操作,進而達到連續改變CCRx值得目的。例如
for(i=0;i<300;i++){
TIM1->CCR1=i;
if(i==300){
i=0;
}
}
這裡還要說的是PWM波的周期是由 定時器時鐘頻率 和 預裝載值 兩者決定的,預裝載值就是ARR。我們來具體分析一下,預裝載值PSC設定為899,那麼,當定時器的目前值val從0增加到899時,一共經過了900個時鐘周期,這900個時鐘周期會産生一個PWM波形,也就是說900個定時器時鐘周期才相當于一個PWM周期,那麼PWM的頻率就為72MHz/900=80KHz,周期為1/80KHz。
有很多同學私信我很多的問題,也有要手冊和源碼的,CSDN下載下傳要積分,我放公衆hao了:遊俠嵌入式。(計科卓越班的可以私我)