STM32电机不转?从代码到原理的3个实战避坑指南:PWM配置、驱动调试全解析

前言

电机明明接好线、代码也烧录了,却死活不转——这大概是每个嵌入式开发者在电机控制开发中都可能遇到的“灵魂拷问”。本文正是一位开发者在STM32电机控制实战中,针对“电机不转”问题的完整排查与复盘记录。

文中不仅还原了从故障现象到解决问题的全过程:从最初发现电机无响应,到通过代码调试定位出宏定义定时器通道配置错误PWM输出比较值过小不足以驱动电机STM32CubeIDE需手动复位才能运行这三大“隐形坑”;还深入解析了底层原理——包括TB6612驱动模块的H桥控制逻辑、PWM占空比与电机转速的关系、定时器配置与电机驱动的匹配原则。

无论你是刚接触STM32电机控制的新手,还是曾被类似问题卡壳的开发者,都能从这篇文章中获得实用经验:学会如何通过代码校验快速定位配置错误、掌握PWM参数调试的关键技巧、避开开发环境的“暗礁”,更能理解电机驱动的核心原理,让你的电机控制开发少走弯路。

一、踩了个小坑——电机怎么着都不转

先将代码都放出来,大家也可以看一下。

1.1 故障代码

1.1.1 main.h

下面是main.h文件的部分内容:

#define LEFT_MOTOR_AIN1 PBout(14)
#define LEFT_MOTOR_AIN2 PBout(15)
#define RIGHT_MOTOR_BIN1 PBout(13)
#define RIGHT_MOTOR_BIN2 PBout(12)

#define LEFT_MOTOR_FORWARD      {LEFT_MOTOR_BIN1=1;LEFT_MOTOR_BIN2=0;}
#define LEFT_MOTOR_BACKWARD     {LEFT_MOTOR_BIN1=0;LEFT_MOTOR_BIN2=1;}
/*电机制动*/
#define LEFT_MOTOR_BRAKE        {LEFT_MOTOR_BIN1=1;LEFT_MOTOR_BIN2=1;}
/*电机停止*/
#define LEFT_MOTOR_STOP         {LEFT_MOTOR_BIN1=0;LEFT_MOTOR_BIN2=0;}


#define RIGHT_MOTOR_FORWARD     {RIGHT_MOTOR_AIN1=1;RIGHT_MOTOR_AIN2=0;}
#define RIGHT_MOTOR_BACKWARD    {RIGHT_MOTOR_AIN1=0;RIGHT_MOTOR_AIN2=1;}
/*电机制动*/
#define RIGHT_MOTOR_BRAKE       {RIGHT_MOTOR_AIN1=1;RIGHT_MOTOR_AIN2=1;}
/*电机停止*/
#define RIGHT_MOTOR_STOP         {RIGHT_MOTOR_AIN1=0;RIGHT_MOTOR_AIN2=0;}

/*use TIM2 for PWM output*/
#define LEFT_MOTOR_PWM_TIM_HANDLE       htim2
#define RIGHT_MOTOR_PWM_TIM_HANDLE      htim2
#define LEFT_MOTOR_PWMA_CHANNEL          TIM_CHANNEL_2
#define RIGHT_MOTOR_PWMB_CHANNEL         TIM_CHANNEL_3

/*use TIM3 for motor encoder*/
#define LEFT_MOTOR_ENCODING_TIM_HANDLE       htim3
#define LEFT_MOTOR_M1A_PA6_TIM3_CH1  TIM_CHANNEL_1
#define LEFT_MOTOR_M1B_PA7_TIM3_CH2  TIM_CHANNEL_2

/*use TIM4 for motor encoder*/
#define RIGHT_MOTOR_ENCODING_TIM_HANDLE        htim4
#define RIGHT_MOTOR_M2A_PB6_TIM4_CH1   TIM_CHANNEL_1
#define RIGHT_MOTOR_M2B_PB7_TIM4_CH2   TIM_CHANNEL_2

1.1.2 main.c

下面是main.c文件部分的内容:

HAL_TIM_PWM_Start(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMA_CHANNEL);
HAL_TIM_PWM_Start(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMB_CHANNEL);

LEFT_MOTOR_FORWARD;
__HAL_TIM_SET_COMPARE(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMA_CHANNEL, 20);
RIGHT_MOTOR_FORWARD;
__HAL_TIM_SET_COMPARE(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMB_CHANNEL, 20);

二、排查故障:PWM引脚直接输出高电平,电机转吗

将原本输出PWM的引脚配置成通用推挽输出功能,让他输出电平,电机是否会转动?

下面的代码省略了PA2配置成通用推挽输出的代码,只写出了将其置为高电平的代码:

    LEFT_MOTOR_FORWARD;
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
    HAL_Delay(1000);
    LEFT_MOTOR_STOP;

上面的代码希望电机正转,1秒钟,之后停止。实际测试结果是电机确实如我们希望的那样,转动了一秒就停下来了。

那么问题一定是定时器没有输出正确的PWM,下面就要排查定时器产生PWM的代码了

2.1 踩坑一:宏定义错误

其实犯的错误很简单,就是定义的宏写错了。
本来左边电机的定时器输出通道是TIM_CHANNEL_3,而我写成了TIM_CHANNEL_2。导致在调用下面的函数HAL_TIM_PWM_Start(),返回了错误,而如果没有使用返回值检测,就一定会遗漏这个问题。

HAL_TIM_PWM_Start(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMA_CHANNEL);

函数内部是这样的:
在这里插入图片描述

跳坑

查看原理图:
在这里插入图片描述
对照STMCubeIDE的配置:
在这里插入图片描述

根据原理图和实际的配置项,细心地检查电机的PWM输出引脚,应该修改为:

/*use TIM2 for PWM output*/
#define LEFT_MOTOR_PWM_TIM_HANDLE       htim2
#define RIGHT_MOTOR_PWM_TIM_HANDLE      htim2 
#define LEFT_MOTOR_PWMA_CHANNEL          TIM_CHANNEL_3
#define RIGHT_MOTOR_PWMB_CHANNEL         TIM_CHANNEL_4

2.2 踩坑二:输出比较值太小

将上面的宏定义修改了之后,两个电机仍旧不转。原因在于,输出比较值太小,导致驱动不了电机!看一下这里的代码:

LEFT_MOTOR_FORWARD;
__HAL_TIM_SET_COMPARE(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMA_CHANNEL, 20);
RIGHT_MOTOR_FORWARD;
__HAL_TIM_SET_COMPARE(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMB_CHANNEL, 20);

按理说,即便上面的宏写错了,也即是左边电机不转。但右边电机应该转的呀!实际上,两边的电机都不转。原因是这里的__HAL_TIM_SET_COMPARE(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMB_CHANNEL, 20);最后一个参数值太小了,不应该是20

跳坑

实际测试了多次,设置100,可以比较正常的转动,再小了就不一定转。
备注:我的定时器重装载寄存器值为1000-1,所以__HAL_TIM_SET_COMPARE设置的值在0-999之间。要综合考虑定时器重装载寄存器的值输出比较的值

2.3 跳坑三、STM32CubeIDE

没错,这个开发环境也有时候闹妖蛾子,大家留一点就行。
在这里插入图片描述

在点击这个按钮,程序下载进去之后,有时候需要我们手动按下复位按键,才可以运行程序。所以如果程序下载进去,电机没反应,按下复位按键试试。

当然可以点击debug按钮,可以直接测试程序。
在这里插入图片描述

即便你从debug中退出了,程序也还是在MCU内部了,他会自动运行。(但不是复位后重新运行哦)

另外在里面配置了之后也有坑,否则新配置的项可能没有生效。
在这里插入图片描述

二、电机转动原理

上面讲完实际操作的时候遇到的问题,下面讲一下电机转动的原理。首先,电机是STM32输出控制信号给TB6612模块,由TB6612来驱动电机的。

2.1 TB6612驱动原理

在这里插入图片描述
图上可以看出来,红色框是一组,绿色框是一组。其中,
PWMAAIN1AIN2是一组输入信号,连接到STM32。这一组的输出信号是AO1AO2,这两个引脚。
另一组的输入是PWMBBIN1BIN2。输出的信号是BO1BO2。看下电机的连接:
在这里插入图片描述
一个电机有两根线的控制来运动的。再看下STM32是怎么连接的。
在这里插入图片描述

而在TB6612驱动模块里,AIN1AIN2控制的是电机的转动方向,比如是正转还是反转。PWMA是控制转动速度的,有占空比决定的。所谓占空比就是一个周期里面,高电平的时间占整个周期时间的比例。

下面是TB6612的芯片内部构造图。

在这里插入图片描述
在这里插入图片描述
至于每一路的控制其实是H桥的原理。

2.1.1 真值表

在这里插入图片描述
只要STBY等于低电平,那么TB6612就处于待机状态,不管其他引脚输入什么信号,都不会有输出,电机也不会转动。原理图上将其直接连接了5V电压,也就不会待机了。

2.2 配置

既然知道了原理,下面就是配置了。

2.2.1 配置电机转动方向控制引脚

在这里插入图片描述

2.2.2 配置PWM

使用TIM2输出PWM信号。

在这里插入图片描述
在这里插入图片描述
改变占空比,实则改变的是CCR寄存器,范围是0-ARR,也就是1-999。
占空比的公式是:占空比=(CCR + 1) / (ARR + 1)
因为计数从0开始的。
在这里插入图片描述
在这里插入图片描述

2.3 代码编写

ret = HAL_TIM_PWM_Start(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMB_CHANNEL);
ret = HAL_TIM_PWM_Start(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMA_CHANNEL);
while(ret != HAL_OK)
{

}

这里充分利用了返回值的作用,避免前面的掉坑。
之后就是改变占空比的操作,还有改变电机的转动方向的操作。


uint16_t leftMotorPwmaDutyRatio = 200;
uint16_t rightMotorPwmbDutyRatio = 200;

LEFT_MOTOR_FORWARD;/*Left motor forward*/
RIGHT_MOTOR_BACKWARD;/*Right motor backward*/
__HAL_TIM_SET_COMPARE(&LEFT_MOTOR_PWM_TIM_HANDLE, LEFT_MOTOR_PWMB_CHANNEL, leftMotorPwmaDutyRatio);
__HAL_TIM_SET_COMPARE(&RIGHT_MOTOR_PWM_TIM_HANDLE, RIGHT_MOTOR_PWMA_CHANNEL, rightMotorPwmbDutyRatio);

至于这里的宏,请参考前面第一章讲到的宏定义。


本文结束,欢迎点赞、收藏、转发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值