STM32單片機(jī)的PWM(脈沖寬度調(diào)制)電機(jī)控制
作者:公子易平
時間:2023/6/6
前段時間做一個智能小車的相關(guān)項目時,發(fā)現(xiàn)很少有人能夠?qū)TM32的PWM控制講清楚,故而書此文,希望對后來的學(xué)習(xí)者有所幫助。
1.硬件介紹
- STM32F103C8T6最小系統(tǒng)板
-
直流TT電機(jī)
-
電機(jī)驅(qū)動芯片(TB6612)
-
-
杜邦線若干
接線情況:
TB6612引腳說明:
STM32主控芯片與TB6612接線:
STM32F103C8T6 | TB6612 |
---|---|
PA6 | PWMA |
PA7 | PWMB |
PB12 | AIN1 |
PB13 | AIN2 |
PB14 | BIN1 |
PB15 | BIN2 |
TB6612其余接口:
TB6612 | 接口 |
---|---|
VM | 7.4V |
VCC | 3.3V |
GND | GND |
AO1&AO2 | A路電機(jī)正負(fù)極 |
BO1&BO2 | B路電機(jī)正負(fù)極 |
STBY | 3.3V |
電路原理圖如下,僅供參考:
2.PWM控制原理
PWM即脈沖寬度調(diào)制(Pulse Width Modulation),常用PWM實現(xiàn)LED呼吸燈、直流電機(jī)調(diào)速以及舵機(jī)控制,本文重點(diǎn)介紹如何使用STM32單片機(jī)對直流電機(jī)進(jìn)行調(diào)速控制。
2.1PWM控制的三個關(guān)鍵參數(shù)
PWM控制的三個關(guān)鍵參數(shù)為頻率(Freq)、占空比(Duty)以及分辨率(Reso),其相關(guān)定義如下式所示。
式中,F(xiàn)req、Duty以及Reso分別表示PWM的頻率、占空比和分辨率。Ts為一個PWM控制周期的總時間,Ton為一個PWM控制周期中高電平時間。式中分辨率和頻率的定義一樣但是單位不同,頻率的單位是Hz,分辨率的單位是%。
需要重點(diǎn)關(guān)注的是占空比和分辨率兩個參數(shù)。
- 占空比:
高電平的工作時間占一個周期的比例,可以理解高電平時間越長則電機(jī)轉(zhuǎn)速越快,反之越慢。
(理想的認(rèn)為占空比和電機(jī)的轉(zhuǎn)速成正比例關(guān)系)
eg:
Duty=0% 電機(jī)不轉(zhuǎn)
Duty=100% (在供電電壓滿足電機(jī)的額定電壓時)電機(jī)達(dá)到最大轉(zhuǎn)速
Duty=50%的電機(jī)轉(zhuǎn)速大于Duty=30%的電機(jī)轉(zhuǎn)速
- 分辨率:
表征PWM控制的精度的一個參數(shù),即可以電機(jī)速度調(diào)節(jié)的步距(Step)的大小,分辨率越大,能夠控制的占空比也就精度越高。
eg:
Reso=1%(1/100) 則電機(jī)的占空比可以為1% 2% 3%…100%,但是不能為3.5%;
Reso=0.1% (1/1000)則電機(jī)的占空比可以為0.1%、8.9%…,但是不能是90.678%。
2.2定時器關(guān)鍵參數(shù)
使用STM32單片機(jī)實現(xiàn)PWM控制時需要用到單片機(jī)上的TIM定時器外設(shè),使用定時器的輸出比較功能。
需要配置的定時器的關(guān)鍵參數(shù)亦有三個:預(yù)分頻值PSC(Prescalar)、自動重裝值A(chǔ)RR(AutoReload Register)以及輸出比較值CCR(Capture /Compare Register)。
- PSC
? 對輸入到定時器中的時鐘進(jìn)行分頻,如果默認(rèn)的輸入時鐘信號為72MHz,則PSC=0時,時鐘信號不分頻,定時器輸入時鐘信號為72MHz;PSC=1時,系統(tǒng)分頻,定時器輸入時鐘信號為36MHz…
? 定時器的輸入時鐘信號=默認(rèn)的輸入時鐘信號?(PSC+1)
- ARR
? 當(dāng)使用定時器時,每經(jīng)過單位時間(時基單元決定),定時器中CNT計數(shù)單元就會加1,其上限值由寄存器的位數(shù)決定,為防止其無限增加,需要配置ARR值。ARR的作用是在CNT計數(shù)單元增加到ARR值時,CNT的值自動停止增加并返回到初始值。
? 實際上可以將這個過程看作給多個杯子加水的過程,每過一段時間就給一個杯子加固定體積的水,當(dāng)一個杯子中的水裝滿之后,就給另一個新的杯子加水,而ARR自動重裝值就相當(dāng)于每個杯子的高度。
- CCR
? 其實CCR輸出比較值可以簡單的理解為一個分界線。
? 依舊是上面的例子,這次我們將杯子更具CCR分界線分成了上下兩部分。下部分空間在遇到水之后會變成綠色,而上部分空間在遇到水之后會變成紅色。
? 在單片機(jī)中將綠色想象成高電平,紅色為低電平。則在一個計數(shù)的周期內(nèi),如果定時器的計數(shù)值CNT未到達(dá)CCR分界線,則水是綠色的,輸出高電平給電機(jī);當(dāng)計數(shù)值CNT到達(dá)分界線CCR,則此時再向水杯中加水,顏色就會變成紅色,即輸出低電平給電機(jī),而當(dāng)水杯裝滿后,又需要給下一個水杯進(jìn)行加水重復(fù)上述過程。
2.3PWM參數(shù)聯(lián)系定時器參數(shù)
上文中已然描述了定時器的三個參數(shù)以及PWM控制的三個參數(shù),最終的目的是將定時器的三個參數(shù)的配置和PWM控制的三個參數(shù)的控制聯(lián)系起來。
其相互之間的聯(lián)系的公式可以由下述公式進(jìn)行描述:
其中ARR值和CCR的值決定了PWM控制的占空比和分辨率。
下圖所示為其原理圖,PWM控制的工作過程為:
- 定時器工作,計數(shù)器值增加。
- 當(dāng)計數(shù)器值N小于CCR時,輸出電平V為高電平1。
- 當(dāng)計數(shù)器值到達(dá)CCR時,輸出電平V翻轉(zhuǎn)為低電平0。
- 當(dāng)計數(shù)器值大于CCR小于ARR時,輸出電平持續(xù)為低電平0,計數(shù)值N繼續(xù)增加。
- 當(dāng)計數(shù)器值達(dá)到ARR時,計數(shù)值N回到初始狀態(tài),同時電平翻轉(zhuǎn),一個周期結(jié)束。
所以,PWM控制實際上就是通過不斷的改變定時器的CCR值來改變占空比,從而實現(xiàn)對電機(jī)的調(diào)速。
3.軟件設(shè)計
TB6612電機(jī)驅(qū)動芯片可以驅(qū)動兩路電機(jī),本次使用單片機(jī)定時器3的兩個通道產(chǎn)生兩路PWM波實現(xiàn)對電機(jī)的調(diào)速控制。以下是代碼部分,使用Keil軟件進(jìn)行編寫。
3.1定時器配置
#include "stm32f10x.h"//頭文件
//初始化定時器TIM3 并配置PWM初始化參數(shù)
void PWM12_Init(void)
{ //開啟TIM3和GPIOA的時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//初始化GPIO口 PA6 PA7 用于產(chǎn)生PWM信號
GPIO_InitTypeDef GPIO_InitStructure;
//復(fù)用推挽輸出模式因為復(fù)用了TIM3外設(shè)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO A6 A7
//使用內(nèi)部時鐘
TIM_InternalClockConfig(TIM3);
//配置時基單元參數(shù)
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//定時器不分頻
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上計數(shù)模式
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;//ARR自動重裝值
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;//PSC預(yù)分頻值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//到達(dá)ARR觸發(fā)一次中斷 停止計數(shù)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//初始化單元
//輸出比較結(jié)構(gòu)體配置
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//補(bǔ)全結(jié)構(gòu)體中未配置參數(shù)
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//選擇PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//輸出比較極性選擇
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//輸出使能
TIM_OC1Init(TIM3, &TIM_OCInitStructure);//初始化 TIM3 OC1
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能CCR1自動重裝
TIM_OC2Init(TIM3, &TIM_OCInitStructure);//初始化 TIM3 OC2
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能CCR2自動重裝
TIM_ARRPreloadConfig(TIM3,ENABLE);//開啟預(yù)裝載
TIM_Cmd(TIM3, ENABLE);//開啟定時器3
TIM3->CCR1 = 0;//設(shè)置輸出比較值
TIM3->CCR2 = 0;
}
//設(shè)置PWM1比較值 為Compare 即輸出比較值
void PWM12_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM3, Compare);
}
//設(shè)置PWM2比較值 為Compare
void PWM12_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM3, Compare);
}
3.2電機(jī)端口初始化
/******************************Motor電機(jī)模塊**************************
電機(jī)初始化設(shè)置 以及電機(jī)PWM設(shè)置
*********************************************************************/
#include "stm32f10x.h" // Device header
#include "Timer.h"
void MotorAll_Init(void)
{
//開啟電機(jī)驅(qū)動口的四個GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13|GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
PWM12_Init();//開啟定時器
}
//設(shè)置右路電機(jī)速度 PWM
void MotorR_SetSpeed(int8_t Speed)
{
if (Speed >= 0)//Speed值為正
{
GPIO_SetBits(GPIOB, GPIO_Pin_12);//電機(jī)正轉(zhuǎn)
GPIO_ResetBits(GPIOB, GPIO_Pin_13);
PWM12_SetCompare1(Speed);//設(shè)置Speed轉(zhuǎn)速
}
else//Speed值為負(fù)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);//電機(jī)反轉(zhuǎn)
GPIO_SetBits(GPIOB, GPIO_Pin_13);
PWM12_SetCompare1(-Speed);//設(shè)為-Speed轉(zhuǎn)速
}
}
//設(shè)置左路電機(jī)PWM 速度
void MotorL_SetSpeed(int8_t Speed)
{
if (Speed >= 0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_14);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
PWM12_SetCompare2(Speed);
}
else
{
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
PWM12_SetCompare2(-Speed);
}
}
3.3小車運(yùn)動封裝
/******************************模塊簡介*******************************
模塊功能:小車運(yùn)動 模塊函數(shù)封裝
*********************************************************************/
#include "stm32f10x.h" // Device header
#include "Motor.h"
#include "Delay.h"
void Car_Stop()//小車停止
{
MotorR_SetSpeed(0);
MotorL_SetSpeed(0);
}
void Car_Up()//小車前進(jìn)
{
MotorR_SetSpeed(80);
MotorL_SetSpeed(80);
}
void Car_Down()//小車后退
{
MotorR_SetSpeed(-80);
MotorL_SetSpeed(-80);
}
void Car_TurnRight()//小車右轉(zhuǎn)
{
MotorR_SetSpeed(-50);
MotorL_SetSpeed(100);
}
void Car_TurnLeft()//小車左轉(zhuǎn)
{
MotorR_SetSpeed(100);
MotorL_SetSpeed(-50);
}
void Car_Spin()//小車旋轉(zhuǎn)
{
MotorR_SetSpeed(-100);
MotorL_SetSpeed(100);
}
在主函數(shù)中分別調(diào)用上述封裝函數(shù),即可實現(xiàn)電機(jī)的調(diào)速運(yùn)動。
上述內(nèi)容僅為作者個人看法,受限于水平和經(jīng)驗原因,部分描述可能存在問題。希望讀者可以指出錯誤的地方,一起交流學(xué)習(xí)。畢竟讀他人的東西只有做到雙眼自將秋水洗,才能一生不受古人欺。
更新日期 :2023/6/8文章來源:http://www.zghlxwxcb.cn/news/detail-556163.html
作 者:公子易平文章來源地址http://www.zghlxwxcb.cn/news/detail-556163.html
到了這里,關(guān)于STM32單片機(jī)PWM控制實現(xiàn)電機(jī)調(diào)速度(小車運(yùn)動,STM32F103C8T6&TB6612&TT電機(jī))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!