01 前言
原來(lái)做的差速小車是基于Arduino控制的,感覺(jué)有些簡(jiǎn)單,也有些基礎(chǔ),Arduino方便簡(jiǎn)單的同時(shí),可操作性感覺(jué)也少了很多,所以想將控制器換成STM32,然后將樹(shù)莓派作為上位機(jī),STM32作為下位機(jī),通過(guò)樹(shù)莓派和STM32進(jìn)行通訊,實(shí)現(xiàn)對(duì)差速移動(dòng)小車的控制,本人也是寒假期間初學(xué)STM32,也是奔著應(yīng)用去的,所以對(duì)于STM32編程原理方面可能不太精通,這里偏重于記錄應(yīng)用層面的知識(shí)。
02 PWM調(diào)速原理
直流電機(jī)驅(qū)動(dòng)是最簡(jiǎn)單的,給電機(jī)通上電就能轉(zhuǎn),根據(jù)電機(jī)的公式:
可知:當(dāng)提高電壓時(shí),反電勢(shì)升高,進(jìn)而轉(zhuǎn)速升高,電壓與轉(zhuǎn)速大致有如圖所示的關(guān)系。
編輯
所以我們只要控制給電機(jī)通電的電壓即可控制電機(jī)的轉(zhuǎn)速,但是在實(shí)際的控制中,控制直流電機(jī)需要通過(guò)H橋控制電機(jī)的正反轉(zhuǎn),如圖,當(dāng)T1和T4二極管導(dǎo)通時(shí),有粉色通路;當(dāng)T2和T3二極管導(dǎo)通時(shí),有藍(lán)色通路,這樣我們就可以實(shí)現(xiàn)弱電控制強(qiáng)電,通過(guò)二極管的通斷來(lái)控制電機(jī)的轉(zhuǎn)向。
但是這樣電機(jī)通電時(shí)電壓就是Us,我們?nèi)绻胱杂傻目刂芔s的電壓值基本是不能實(shí)現(xiàn)的,因?yàn)殡姍C(jī)是接到單片機(jī)的引腳上的,引腳的供電電壓值是確定的,我們就要使用控制二極管的通斷時(shí)間對(duì)電機(jī)的轉(zhuǎn)速進(jìn)行控制,即PWM控制。
圖中的D1~D4二極管為續(xù)流的作用,因?yàn)殡姍C(jī)中有繞組,在斷電后,電感的電流不能瞬時(shí)變?yōu)?,所以在斷電后電流沿棕色和綠色的通路放點(diǎn)電。
在一個(gè)周期內(nèi),我們通過(guò)控制通電的時(shí)間就可以調(diào)控平均電壓,而平均電壓的高低直接控制電機(jī)的轉(zhuǎn)速,通電時(shí)間/周期,就可以得到占空比,我們也就是通過(guò)控制電機(jī)的占空比來(lái)控制電機(jī)的轉(zhuǎn)速的。
在實(shí)際應(yīng)用過(guò)程中,我們不用自己搭建H橋,而是使用電機(jī)驅(qū)動(dòng)板(如:L298N)對(duì)直流電機(jī)進(jìn)行驅(qū)動(dòng),L298N內(nèi)搭載兩個(gè)H橋電路,可以實(shí)現(xiàn)對(duì)兩個(gè)電機(jī)的轉(zhuǎn)向和轉(zhuǎn)速進(jìn)行控制。
這是淘寶商家提供的電機(jī)驅(qū)動(dòng)板控制表,將IN1~4接到單片機(jī)的引腳,我們就可以通過(guò)引腳輸出PWM控制信號(hào),對(duì)直流電機(jī)進(jìn)行控制。
03 STM32編程實(shí)現(xiàn)
在STM32中如果想輸出PWM信號(hào),需要借助定時(shí)器,通過(guò)定時(shí)器的捕獲/比較通道的PWM輸出
當(dāng)我們對(duì)定時(shí)器設(shè)置了預(yù)裝載值arr和比較值ccr后,可以通過(guò)配置PWM模式,使定時(shí)器CNT計(jì)數(shù)值超過(guò)ccr后產(chǎn)生有效信號(hào),并通過(guò)配置相應(yīng)寄存器設(shè)置有效信號(hào)是1還是0,而配置PWM的輸出方式,具體原理信息可以參考原子哥的視頻,也可以參考中文參考手冊(cè)的14.4.7內(nèi)容。
在程序中,我們使用庫(kù)函數(shù)進(jìn)行配置,配置步驟如下:
- 使能定時(shí)器和相關(guān)外設(shè)引腳時(shí)鐘 :RCC_APBxPeriphClockCmd()
- 配置IO口為復(fù)用輸出模式(查手冊(cè)8.1.11)配置成相應(yīng)的模式(復(fù)用推挽輸出)
- 初始化定時(shí)器:TIM_TimeBaseInit()
- 初始化TIM2 Channe1234 PWM模式:TIM_OCxInit()
- 使能OCx通道的預(yù)裝載寄存器:TIM_OC1PreloadConfig()
- 使能時(shí)鐘:TIM_Cmd()
- 在主函數(shù)中配置占空比進(jìn)行調(diào)速:TIM_SetCompare1()
#include "sys.h"
/********************
功能:通用時(shí)鐘2用來(lái)產(chǎn)生通道1234四路PWM信號(hào)
函數(shù):TIM2_PWM_Init(u16 arr,u16 psc)
作者:K.Fire
日期:2022.01.30
引腳:PA0 PA1 PA2 PA3
參數(shù):arr:自動(dòng)重裝值 psc:時(shí)鐘預(yù)分頻數(shù)
*****************/
void TIM2_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//使能GPIOA外設(shè)模塊時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//設(shè)置引腳為復(fù)用輸出功能,輸出TIM2 CH1的PWM脈沖波形 GPIOA.0
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM2_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//設(shè)置引腳為復(fù)用輸出功能,輸出TIM2 CH2的PWM脈沖波形 GPIOA.1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2_CH2
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//設(shè)置引腳為復(fù)用輸出功能,輸出TIM2 CH3的PWM脈沖波形 GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //TIM2_CH3
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//設(shè)置引腳為復(fù)用輸出功能,輸出TIM2 CH4的PWM脈沖波形 GPIOA.3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //TIM2_CH4
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//使能定時(shí)器2時(shí)鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//初始化TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//初始化TIM2 Channe1234 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
TIM_OC1Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC1
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC2
TIM_OC3Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC3
TIM_OC4Init(TIM2, &TIM_OCInitStructure); //根據(jù)T指定的參數(shù)初始化外設(shè)TIM2 OC4
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的預(yù)裝載寄存器
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR3上的預(yù)裝載寄存器
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR4上的預(yù)裝載寄存器
TIM_Cmd(TIM2, ENABLE); //使能TIM2
}