关于PWM调速的原理,其实在之前89C52开发小车的时候也已经详细的描述过,所以主要的区别还是STM32和89C52的PWM实现区别。
关于STM32的PWM实现,是从CubeMX的配置开始的:
CubeMX
1. 在上节的CubeMX项目基础上进行修改
2. 两路PWM分别选择TIM2的CH1(对应PA0)和 TIM2的CH2(对应PA1),PWM的周期为20ms,在Tclk = 72000 000的前提下,将PSC设置为7199;ARR设置为199
另外,还要强调一点和89C52控制小车调速不同的地方:
- 89C52中,生成PWM波后,在有效电平期间,对控制电机的引脚写数据让轮子进行前进或后退
- 而在STM32中,我直接将控制电机的引脚配成了时钟的PWM波输出
所以:
我如果希望对“前进”调速,应该将两路的PWM的有效电平设置为LOW,并把PB1和PB10的GPIO初值设为HIGH;
我如果希望对“后退”调速,应该将两路的PWM的有效电平设置为HIGH,并把PB1和PB10的GPIO初值设为LOW;
此处,我希望对前进调速,所以“应该将两路的PWM的有效电平设置为LOW,并把PB1和PB10的GPIO初值设为HIGH”
2.1 同时注意,由于刚刚配置了PA0和PA1为GPIO的输出,所以TIM2的CH1和CH2会自动分配到其他复用引脚上,所以要将PA0和PA1设置回TIM2的CH1和CH2输出:
3. 惯例设置更新代码
Keil
ARR的199对应20ms,所以CCRx的值是0到199,每增加1就说明在一个周期(20ms)内,增加了 20/199 约等于0.1ms的 有效电平持续时间!
void speed_left(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, speed);//左轮调速
}
void speed_right(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, speed);//左轮调速
}
int main(void)
{
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //打开Timer2的1号Channel, 1号通道对应 左轮
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); //打开Timer2的2号Channel, 2号通道对应 右轮
while (1)
{
speed_left(140);
speed_right(199);
}
}
实现效果
可见,右轮速度全力运转,而左轮则慢些,这就是PWM实现的两轮分别调速:
代码封装
在代码测试成功后,将两轮分别调速的代码封装到motor.c中:
motor.c:
#include "motor.h"
#include "gpio.h"
#include "tim.h"
#define left_B_1A_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET)
#define left_B_1A_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET)
#define left_B_1B_HIGH HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET)
#define left_B_1B_LOW HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET)
#define right_A_1A_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET)
#define right_A_1A_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET)
#define right_A_1B_HIGH HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET)
#define right_A_1B_LOW HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET)
void move_backward(void) //后退
{
left_B_1A_HIGH;
left_B_1B_LOW;
right_A_1A_HIGH;
right_A_1B_LOW;
}
void move_forward(void) //前进
{
left_B_1A_LOW;
left_B_1B_HIGH;
right_A_1A_LOW;
right_A_1B_HIGH;
}
void move_leftturn(void) //左转
{
left_B_1A_LOW; //左轮不动
left_B_1B_LOW;
right_A_1A_LOW; //右轮往前
right_A_1B_HIGH;
}
void move_rightturn(void) //右转
{
left_B_1A_LOW; //左轮往前
left_B_1B_HIGH;
right_A_1A_LOW; //右轮不动
right_A_1B_LOW;
}
void move_stop(void) //停止
{
left_B_1A_LOW;
left_B_1B_LOW;
right_A_1A_LOW;
right_A_1B_LOW;
}
void speed_left(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, speed);//左轮调速
}
void speed_right(int speed) //speed就是CCRx的值,理论在0到199之间,实际最好大于130
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, speed);//左轮调速
}
motor.h:
#ifndef __motor_H__ // "XXXX"就是h文件的名字
#define __motor_H__
void move_backward(void);
void move_forward(void);
void move_leftturn(void);
void move_rightturn(void);
void move_stop(void);
void speed_left(int speed);
void speed_right(int speed);
#endif