上文可了解了PWM的基本原理和相关配置,此文详细了解一下PWM如何驱动电机的
目标: 实现利用STM32F103C8T6+TB6612,输出不同占空比输出的PWM波,从而实现电机不同转速的运行、正反转的功能;
1、概述
直流电机是一种电能转化为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。
直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作。使用驱动方案有两种:一是根据自己所学的电路知识或仿照他人电路,使用MOS管搭建电路,设计所需的驱动电路;二是采用购买现有的驱动电路芯片,使用芯片驱动。
这里采用TB6612芯片来作为驱动电路,TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向。
2、驱动电路
如图为芯片的硬件电路图,芯片可以驱动两个电机,A表示电机1;B表示电机2。VM接电机所需的电压,若电机所需电压为5V,则接5V;所需10V则接10v。
单片机输出一路PWM信号和两路GPIO输出控制信号,接到驱动电路的PWM和IN1,IN2三个引脚,经由芯片输出O1和O2,驱动电机。
如下图所示为芯片上的引脚定义,STBY为控制引脚,接高电平则芯片工作。电机正转反转,制动如下图所示。由PWM,IN1,IN2三个引脚控制电机的制动/正转/反转。
2.1、H桥型驱动电路
如图为H桥型的驱动电路,若1导通2断开,则O1接VM,若1断开2导通,则O1接GND。O2同理。若O1O2中间接上电机,则当14导通,23断开时,电机正转。当14断开,23导通时,电机反转。
TB6612芯片是双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向。
2.2、单级驱动电路
电机单向控速
3、软件程序
3.1介绍
目标:单片机输出一个PWM信号,驱动电机正转/反转/停止。PWM占空比高,则转速快;PWM占空比低,则转速慢;
如下图为实物连接图,三根输出信号线,一路输出PWM信号控制电机转速,另两路为控制电机正转反转的状态。
3.2程序运行思路分析:
1)打开时钟(TIM和GPIO的时钟)
2)初始化GPIO(指定某个引脚输出PWM信号,指定另两个引脚为控制转向引脚)
3)初始化定时器时基单元,(为了设置定时器参数,如频率,计数模式,ARR自动重装值,PSC预分频器等)
4)初始化定时器输出比较,(配置某个定时器的某个通道,模式,极性,使能,和CCR捕获比较寄存器)
5)开启定时器
6)函数调用,调用函数实现自己所需功能
3.3程序
下面这端程序为PWM信号的初始化,包括时钟打开,GPIO,时基单元,输出比较的初始化。
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /打开TIM和GPIO的时钟
GPIO_InitTypeDef GPIO_InitStructure; /GPIO初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure; /定时器输出比较初始化
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE); /开启定时器
}
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2, Compare); /调用这个函数可更改CCR的值,通过更改CCR的值改变PWM占空比
}
下面这段代码是对另两个控制引脚的初始化
void Motor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
PWM_Init();
}
下面这段代码,是调用函数,来设置我们想要的电机速度。
void Motor_SetSpeed(int8_t Speed)
{
if (Speed >= 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4); /这两个引脚设置一高一低电平,则表示正转
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(Speed); /再调用函数,设置CCR的值改变PWM占空比,达到设置电机速度的目的
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4); /同理,这里为反转
GPIO_SetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(-Speed);
}
}
以上代码,是在子函数中进行的,为主函数的调用做准备。下面这段代码,是在主函数调用,表示按键按下,速度加20。当速度超过时,变为-100。再重新累计。
效果:按下按键,电机速度就会增加,电机最大后,电机会反转。
int main(void)
{
OLED_Init();
Motor_Init();
Key_Init();
OLED_ShowString(1, 1, "Speed:");
while (1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
Speed += 20;
if (Speed > 100)
{
Speed = -100;
}
}
Motor_SetSpeed(Speed);
OLED_ShowSignedNum(1, 7, Speed, 3);
}
}
4、程序功能解释
4.1、PWM输出流程图
系统时钟频率出来,经过预分频器和自动重装器,可输出固定频率的信号,
设计计数模式,如图中的向上计数模式,从0计数到ARR,再自动重装为0,不断循环。
当经过比较器的时候,比较计数值CNT与CCR的值,选择比较的模式(PWM1和PWM2),如PWM1模式:CNT<CCR,则输出高电平。
如此经过比较器后,就输出高低电平不同宽度的PWM波形了。
4.2、PWM占空比计算
计算PWM占空比的计算方式为:如图为输出50%PWM信号,1KHZ。
4.3、时基单元初始化函数
TIM_TimeBaseInit函数,TIM_TimeBaseInitTypeDef结构体参数有:
TIM_Prescaler,预分频器值,也就是PSC值。
TIM_CounterMode,计数模式,一般为向上计数模式,
TIM_Period,自动重装值,ARR.
TIM_ClockDivision,预分频,多少分频,对72MHZ的频率进行除法,一分频则不变。
TIM_RepetitionCounter,不太理解,给的是0
4.4输出比较初始化函数
以上函数是用来配置输出比较模块的,每个函数对应一个定时器的通道,配合结构体使用。
TIM_OCInitTypeDef,结构体参数有:
TIM_OCMode:输出比较模式,PWM应用中就PWM1和PWM2两种模式,其他有冻结/有效/无效/反转等用不到的模式。
TIM_OutputState:输出使能
TIM_OutputNState:输出失能
TIM_Pulse:比较器值CCR, 0x0000 and 0xFFFF之间的值。
TIM_OCPolarity:极性,TIM_OCNPolarity_High,TIM_OCNPolarity_Low
TIM_OCNPolarity:同上
TIM_OCIdleState:未理解,没用到
TIM_OCNIdleState:未理解,没用到
如上面几个在程序中未用到的参数,就可以调用函数TIM_OCStructInit(&TIM_OCInitStructure);,给他们统一赋初始值。
下图为输出比较模式的详解图:
4.5设置CCR值
以上函数是用来更改占空比的,调整CCR的值来改变占空比,
参考: