STM32 HAL库驱动TB6612模块精准控制编码电机转速与转向附CubeMX配置在智能小车、机械臂等嵌入式项目中电机控制往往是核心环节。TB6612作为一款高效直流电机驱动芯片配合STM32的PWM输出和编码器接口能够实现精准的转速与方向控制。本文将手把手带你完成从CubeMX配置到闭环控制的全流程实现。1. 硬件架构与工作原理TB6612FNG采用MOSFET构建H桥电路相比传统晶体管方案具有更低导通损耗和更高开关频率。其核心功能可分解为三个部分功率驱动VM引脚输入4.5-15V驱动电压通过AO1/AO2和BO1/BO2输出到电机逻辑控制VCC引脚2.7-5.5V供电接收来自MCU的PWM和方向信号保护机制内置过热关断和低压检测电路编码电机则通过正交编码器提供转速反馈典型接线方式如下线序功能描述连接目标1电机正极TB6612 AO1/AO22编码器GNDMCU GND3编码器B相正交信号定时器输入通道4编码器A相正交信号定时器输入通道5编码器电源通常5VMCU 5V输出6电机负极TB6612 AO1/AO22. CubeMX基础配置2.1 PWM生成配置选择高级定时器如TIM1/TIM8开启PWM Generation模式设置预分频器(Prescaler)和自动重载值(ARR)// 示例72MHz主频下生成20kHz PWM htim1.Instance-PSC 71; // 72MHz/(711) 1MHz htim1.Instance-ARR 49; // 1MHz/(491) 20kHz配置Pulse值为ARR的一半作为初始占空比2.2 编码器接口配置选择通用定时器如TIM2-TIM5设置为Encoder Mode配置通道极性为Rising Edge设置编码器分辨率// 4倍频计数模式 htim2.Init.Period 65535; // 16位最大值2.3 GPIO控制引脚引脚功能模式设置初始化状态AIN1Output Push-PullLowAIN2Output Push-PullLowSTBYOutput Push-PullHigh3. 电机驱动实现3.1 方向控制逻辑根据TB6612真值表实现方向控制函数void Motor_SetDirection(GPIO_TypeDef* IN1_Port, uint16_t IN1_Pin, GPIO_TypeDef* IN2_Port, uint16_t IN2_Pin, MotorDirection dir) { switch(dir) { case MOTOR_BRAKE: HAL_GPIO_WritePin(IN1_Port, IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IN2_Port, IN2_Pin, GPIO_PIN_RESET); break; case MOTOR_CW: HAL_GPIO_WritePin(IN1_Port, IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IN2_Port, IN2_Pin, GPIO_PIN_SET); break; case MOTOR_CCW: HAL_GPIO_WritePin(IN1_Port, IN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(IN2_Port, IN2_Pin, GPIO_PIN_RESET); break; } }3.2 速度控制实现PWM占空比调节函数示例void Motor_SetSpeed(TIM_HandleTypeDef* htim, uint32_t Channel, uint16_t duty) { // 限制占空比范围 duty (duty htim-Instance-ARR) ? htim-Instance-ARR : duty; switch(Channel) { case TIM_CHANNEL_1: htim-Instance-CCR1 duty; break; case TIM_CHANNEL_2: htim-Instance-CCR2 duty; break; // 其他通道处理... } }4. 编码器测速与闭环控制4.1 速度计算采用定时中断法测量转速// 全局变量 int32_t encoder_count 0; float rpm 0.0f; // 定时器中断回调 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim htim3) { // 1ms定时器 static int32_t last_count 0; int32_t delta encoder_count - last_count; // 计算RPMdelta/(PPR*4) * (60000/采样周期ms) rpm (delta / (13.0f * 4)) * (60000.0f / 10.0f); last_count encoder_count; encoder_count 0; // 清零计数器 } }4.2 简易PID控制器实现位置式PID算法typedef struct { float Kp, Ki, Kd; float integral; float prev_error; } PID_Controller; float PID_Update(PID_Controller* pid, float setpoint, float measurement) { float error setpoint - measurement; pid-integral error; if(pid-integral 1000) pid-integral 1000; if(pid-integral -1000) pid-integral -1000; float derivative error - pid-prev_error; pid-prev_error error; return pid-Kp * error pid-Ki * pid-integral pid-Kd * derivative; }5. 系统集成与调试技巧5.1 典型问题排查现象可能原因解决方案电机不转STBY引脚未使能检查STBY引脚是否为高电平只有一个转向方向控制逻辑错误验证真值表实现代码PWM无输出定时器未启动调用HAL_TIM_PWM_Start()编码器读数异常信号线接触不良检查接线并添加上拉电阻5.2 性能优化建议PWM频率选择普通直流电机5-20kHz空心杯电机建议25kHz抗干扰措施// 在编码器输入引脚配置上拉 GPIO_InitStruct.Pull GPIO_PULLUP;速度滤波算法// 移动平均滤波 #define FILTER_SIZE 5 float speed_buffer[FILTER_SIZE]; float filtered_speed(float new_speed) { static uint8_t index 0; speed_buffer[index] new_speed; if(index FILTER_SIZE) index 0; float sum 0; for(uint8_t i0; iFILTER_SIZE; i) { sum speed_buffer[i]; } return sum / FILTER_SIZE; }在实际项目中我发现电机启动时的电流冲击容易导致MCU复位。通过增加软启动算法——即PWM占空比从0开始按指数曲线递增能有效避免这个问题。具体实现时可以将目标速度作为PID的设定值而不是直接控制PWM占空比。