STM32结合TB6612实现双路直流电机PWM调速与方向控制
1. 从零开始为什么选择STM32TB6612这对黄金搭档如果你正在捣鼓机器人、智能小车或者任何需要让轮子转起来的项目那么“如何精准控制直流电机”绝对是你绕不开的第一个坎。我刚开始玩嵌入式那会儿也试过直接用单片机IO口去驱动电机结果不是电流太小带不动就是芯片发烫到能煎鸡蛋。后来才明白驱动电机这事儿得交给专业的“司机”——电机驱动芯片而TB6612就是一位非常靠谱的“老司机”。简单来说STM32是大脑负责思考和发号施令TB6612是强健的四肢和肌肉负责执行大脑的命令并输出强大的动力。STM32产生的PWM信号就像是我们给电机的“油门”指令而TB6612则负责将这个微弱的数字信号转换成足以驱动电机转动的强大电流。这种组合的优势非常明显STM32编程灵活资源丰富你可以轻松实现复杂的调速算法、多电机协同而TB6612集成度高性能强劲且稳定它内部集成了双H桥能同时独立驱动两个电机还自带过热保护和低压检测大大降低了烧芯片的风险。相比于另一个常见的驱动芯片L298NTB6612的发热量更小效率更高外围电路也更简单特别适合对空间和功耗有要求的移动平台。所以无论你是想做一个能灵活避障的循迹小车还是一个需要平稳云台控制的机器人STM32搭配TB6612都是一个经过无数项目验证的、高效且可靠的方案。接下来我就带你一步步拆解如何让这对搭档完美协作实现电机的“指哪打哪”。2. 硬件连接给STM32和TB6612“牵线搭桥”硬件连接是第一步也是确保后续一切顺利的基础。这一步搞错了代码写得再漂亮电机也不会动。别担心连接其实很有规律我们像搭积木一样把它理清楚。首先我们得认识一下TB6612这位“司机”的几个关键接口。芯片上引脚不少但核心的就那么几组电源部分VM接电机电源比如7.2V的电池VCC接逻辑电源通常接STM32的3.3V或5VGND接地。这里有个关键点电机电源和逻辑电源的地GND必须共地这是它们之间信号沟通的基础。控制信号部分这是STM32与TB6612对话的通道。对于每一个电机假设叫电机A需要三个信号AIN1和AIN2控制方向PWMA控制速度。电机B同理对应BIN1、BIN2和PWMB。STBY是待机引脚高电平芯片才工作通常我们直接接高电平VCC或者用一个STM32的GPIO控制方便紧急制动。电机输出部分AO1和AO2输出给电机A的两极BO1和BO2输出给电机B。理解了引脚连接就水到渠成了。以最常见的STM32F103C8T6蓝色pill开发板为例我们可以这样规划连线STM32引脚TB6612引脚功能说明PA0 (TIM2_CH1)PWMA电机A的PWM速度信号PA1AIN1电机A的方向信号1PA2AIN2电机A的方向信号2PA3 (TIM2_CH2)PWMB电机B的PWM速度信号PA4BIN1电机B的方向信号1PA5BIN2电机B的方向信号2PA6STBY待机控制高电平有效3.3VVCC逻辑电源电池正极VM电机动力电源注意电压范围GNDGND共地注意上表中将PWM信号连接到TIM2的通道1和通道2是因为TIM2是一个通用定时器方便产生两路独立的PWM。你也可以根据自己板子的引脚布局选择其他有PWM输出功能的定时器通道比如TIM1、TIM3、TIM4等原理完全一样。在实际焊接或插线时我建议你先给STM32和TB6612分别供电共地然后用杜邦线连接信号线。接好后务必再三检查电源有没有接反、地线是否连通。我见过太多新手因为一根地线没接好调试了半天程序却发现是硬件问题。确认无误后我们就可以进入激动人心的软件部分了。3. 软件基石配置STM32的PWM与GPIO硬件通路建立好了现在需要让STM32的大脑“动”起来学会发出正确的控制信号。这里我们分两步走一是配置GPIO控制电机的方向二是配置定时器产生PWM波控制速度。我习惯使用STM32CubeMX这个图形化工具来初始化它非常直观能避免很多底层寄存器的繁琐操作。3.1 使用STM32CubeMX进行可视化配置首先在CubeMX里选择你的芯片型号比如STM32F103C8Tx。然后我们开始配置引脚配置方向控制GPIO找到PA1、PA2、PA4、PA5、PA6这几个引脚将它们设置为GPIO_Output模式。你可以给它们起个有意义的标签比如MOTOR_A_IN1、MOTOR_A_IN2等这样生成的代码可读性更好。配置PWM定时器我们需要一个定时器来产生两路PWM。以TIM2为例找到TIM2将Channel1和Channel2的模式设置为PWM Generation CH1和PWM Generation CH2。这时PA0和PA3会自动被配置为复用推挽输出Alternate Function Push Pull。设置PWM关键参数这是核心点击Parameter Settings选项卡我们需要设置两个值Prescaler预分频器PSC和Counter Period自动重装载值ARR。PWM频率由它们共同决定。公式是PWM频率 定时器时钟源 / ( (PSC 1) * (ARR 1) )。对于STM32F103如果系统时钟是72MHz定时器挂在APB1总线上时钟也是72MHz。假设我们想要一个10kHz的PWM频率这个频率对于大多数直流电机来说很合适既能保证响应噪音也小。计算一下PSC可以设为71ARR设为999。那么频率 72,000,000 / ((711)*(9991)) 72,000,000 / 72,000 1000Hz等等这里我故意留了个坑。实际上(PSC1)和(ARR1)是分频和计数周期。如果我们设PSC71ARR999频率 72M / (72 * 1000) 1000Hz也就是1kHz。如果你想得到10kHz可以设PSC71ARR99这样频率 72M / (72 * 100) 10kHz。或者设PSC7ARR899频率 72M / (8 * 900) 10kHz。根据你的电机特性调整一般1kHz到20kHz都可以。将Pulse脉冲值即初始的CCR比较寄存器值设为0这样初始占空比为0%电机不转。最后配置好系统时钟RCC选择好调试接口如Serial Wire就可以生成代码了。3.2 理解生成的代码并编写控制函数CubeMX会为你生成完整的初始化代码。在main.c中你会看到MX_TIM2_Init()和MX_GPIO_Init()函数。我们需要做的是在初始化之后启动PWM输出并编写简洁的电机控制函数。在/* USER CODE BEGIN 2 */和/* USER CODE END 2 */之间添加PWM启动代码/* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); // 启动电机A的PWM通道 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_2); // 启动电机B的PWM通道 HAL_GPIO_WritePin(MOTOR_STBY_GPIO_Port, MOTOR_STBY_Pin, GPIO_PIN_SET); // 使能TB6612退出待机 /* USER CODE END 2 */接下来我们编写两个非常实用的电机控制函数。把它们放在main.c的/* USER CODE BEGIN 4 */区域或者单独的motor.c文件里。函数的思路是通过方向参数设置IN1和IN2的电平组合通过速度参数设置PWM的占空比。/** * brief 控制电机A * param direction: 方向1正转-1反转0刹车/停止 * param speed: PWM比较值范围0-ARR例如ARR999则范围0-999 * retval None */ void MotorA_Ctrl(int8_t direction, uint16_t speed) { switch(direction) { case 1: // 正转 HAL_GPIO_WritePin(MOTOR_A_IN1_GPIO_Port, MOTOR_A_IN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_A_IN2_GPIO_Port, MOTOR_A_IN2_Pin, GPIO_PIN_RESET); break; case -1: // 反转 HAL_GPIO_WritePin(MOTOR_A_IN1_GPIO_Port, MOTOR_A_IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_A_IN2_GPIO_Port, MOTOR_A_IN2_Pin, GPIO_PIN_SET); break; case 0: // 刹车短接电机两端或停止高阻态 // 方式一刹车快速停止 // HAL_GPIO_WritePin(MOTOR_A_IN1_GPIO_Port, MOTOR_A_IN1_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(MOTOR_A_IN2_GPIO_Port, MOTOR_A_IN2_Pin, GPIO_PIN_SET); // 方式二停止自由滑行 HAL_GPIO_WritePin(MOTOR_A_IN1_GPIO_Port, MOTOR_A_IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_A_IN2_GPIO_Port, MOTOR_A_IN2_Pin, GPIO_PIN_RESET); break; } // 设置PWM占空比speed越大占空比越高转速越快 __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, speed); } // 电机B的控制函数MotorB_Ctrl与之类似只需修改对应的GPIO引脚和PWM通道为CHANNEL_2即可。这样我们就拥有了一个可以随意指挥电机的函数。想让它正转半速调用MotorA_Ctrl(1, 500)假设ARR999。想反转全速MotorA_Ctrl(-1, 999)。想停车MotorA_Ctrl(0, 0)。是不是非常清晰4. 核心控制逻辑让电机听你的话有了控制函数我们就可以在main函数的循环里或者在任何需要的地方灵活地编排电机的动作了。这才是真正体现你项目智能的地方。我们来设计几个经典的应用场景看看如何调用这些函数。4.1 基础运动控制前进、后退与转向假设我们的小车是两个轮子差分驱动的。那么基本的运动可以这样实现void Car_Forward(uint16_t speed) { MotorA_Ctrl(1, speed); // 左轮正转 MotorB_Ctrl(1, speed); // 右轮正转 } void Car_Backward(uint16_t speed) { MotorA_Ctrl(-1, speed); // 左轮反转 MotorB_Ctrl(-1, speed); // 右轮反转 } void Car_TurnLeft(uint16_t speed) { // 差速转弯左轮反转右轮正转 MotorA_Ctrl(-1, speed); MotorB_Ctrl(1, speed); } void Car_TurnRight(uint16_t speed) { // 差速转弯左轮正转右轮反转 MotorA_Ctrl(1, speed); MotorB_Ctrl(-1, speed); } void Car_Stop(void) { MotorA_Ctrl(0, 0); MotorB_Ctrl(0, 0); }然后在你的主循环里可以加入一些简单的逻辑比如让小车先前进2秒再左转1秒最后停止。while (1) { Car_Forward(700); // 70%速度前进 HAL_Delay(2000); Car_TurnLeft(500); // 50%速度左转 HAL_Delay(1000); Car_Stop(); HAL_Delay(1000); }下载程序到板子上你应该就能看到小车按照你的指令运动了。第一次看到自己写的代码让轮子精准转动时那种成就感是非常棒的。4.2 高级调速技巧实现平滑加速与减速直接让电机从0速跳到全速不仅耗电对机械结构也有冲击。更优雅的方式是实现加减速。一个简单的方法是线性改变PWM的占空比。void Motor_SmoothStart(TIM_HandleTypeDef *htim, uint32_t Channel, uint16_t target_speed, uint16_t step, uint16_t delay) { uint16_t current_speed __HAL_TIM_GET_COMPARE(htim, Channel); if(current_speed target_speed) { for(uint16_t s current_speed; s target_speed; s step) { __HAL_TIM_SET_COMPARE(htim, Channel, s); HAL_Delay(delay); } } else if(current_speed target_speed) { for(uint16_t s current_speed; s target_speed; s - step) { __HAL_TIM_SET_COMPARE(htim, Channel, s); HAL_Delay(delay); } } // 最终确保达到目标速度 __HAL_TIM_SET_COMPARE(htim, Channel, target_speed); }这个函数会以step为步长delay为间隔逐步将当前速度调整到目标速度。你可以调用Motor_SmoothStart(htim2, TIM_CHANNEL_1, 800, 10, 20)让电机A在约1.6秒内(800/10)*20ms平滑加速到80%的占空比。在实际的机器人项目中这种平滑控制对于提升运动稳定性和用户体验至关重要。4.3 融入传感器反馈构建闭环控制开环控制只管发命令不管电机实际转得怎么样在负载变化时速度会不稳。要实现精准控制比如让小车保持恒定速度爬坡就需要引入编码器来构成速度闭环。编码器可以测量电机轴的实际转速反馈给STM32。STM32的定时器有专门的编码器接口模式可以轻松读取正交编码器的脉冲。基本思路是配置一个定时器如TIM4为编码器模式连接编码器的A、B相。定时读取定时器的计数器值这个值的变化量就代表了电机的转速。将读取到的实际速度与期望速度进行比较得到误差。使用PID控制器根据误差计算出新的PWM占空比并输出给TB6612。不断重复2-4步形成一个闭环使实际速度紧紧跟随期望速度。这部分的代码会复杂一些涉及到PID算法的实现和参数整定但它是从“能动”到“精准控制”的关键飞跃。一旦调好了PID参数你的小车就能在光滑的地面、粗糙的地毯甚至缓坡上都保持几乎一致的速度这才是真正智能的体现。5. 避坑指南与实战经验分享搞定了基本原理和代码最后我想分享几个在实际项目中容易踩的“坑”这些都是我用真金白银烧坏的芯片和无数调试时间换来的经验。第一个大坑是电源。TB6612的VM电机电源和VCC逻辑电源一定要分开供电并且务必共地。我强烈建议使用两套电池或电源一套大容量的锂电池如7.4V给VM供电驱动电机另一套可以用稳压模块从电机电源降压得到5V或3.3V或者直接用另一块小电池给STM32和TB6612的VCC供电。千万不要试图用STM32开发板上的USB 5V来同时给逻辑和电机供电电机启动瞬间的大电流很容易导致STM32复位甚至损坏。电源输入端记得并联一个大电容比如100uF的电解电容加一个0.1uF的瓷片电容可以有效吸收电机启停产生的电压尖峰。第二个是关于PWM频率的选择。频率太低比如几十Hz电机会听到明显的“滋滋”声而且可能转动不连续。频率太高比如超过20kHz虽然听不到声音了但TB6612内部的MOS管开关损耗会增加可能导致芯片发热。对于普通的直流减速电机1kHz到10kHz是一个比较理想的区间。你可以根据自己电机的特性通过修改PSC和ARR的值来调整频率找到一个兼顾性能、噪音和发热的平衡点。第三个是散热问题。虽然TB6612比L298N凉快很多但在驱动大电流电机接近1.2A或长时间堵转时发热依然可观。务必给TB6612芯片贴上一个小散热片或者保持空气流通。在设计PCB时芯片底部的散热焊盘要大面积铺铜并打过孔连接到背面地层这是最重要的散热途径。第四个是软件上的“死区”问题。虽然TB6612内部H桥本身有防短路逻辑但在我们控制方向切换时最好在代码里加入一个短暂的延时。比如从正转切换到反转先让电机刹车IN11, IN21几个毫秒再设置反转的IO状态这样可以进一步避免瞬间的电流冲击。一个健壮的方向控制函数可以这样写void SetMotorDirection(Motor_TypeDef motor, int8_t dir) { // 先刹车 if(motor MOTOR_A) { HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_SET); } // ... 电机B同理 HAL_Delay(5); // 刹车5毫秒 // 再设置新的方向 // ... 原有的方向设置代码 }最后调试时一定要有耐心。如果电机不转首先用万用表或逻辑分析仪检查STM32的PWM引脚和方向引脚是否有正确的输出。如果没有回头检查代码和CubeMX配置。如果有信号但电机还是不转检查TB6612的STBY引脚是否为高电平检查电机电源是否正常检查电机本身是否完好。按照这个顺序排查大部分问题都能迎刃而解。

相关新闻

基于Arduino的智能宠物喂养与家居控制一体化方案

基于Arduino的智能宠物喂养与家居控制一体化方案

1. 从零开始:为什么选择Arduino打造你的智能宠物与家居中心? 如果你和我一样,既是个技术爱好者,又是个“铲屎官”,那你肯定也想过这个问题:能不能有个东西,既能按时按点、风雨无阻地照顾好家里的…

2026/7/8 7:42:33 阅读更多 →
Qt陷阱:QDialog回车键关闭窗口的连环坑与终极避坑指南

Qt陷阱:QDialog回车键关闭窗口的连环坑与终极避坑指南

1. 从一次诡异的“回车关闭”说起 那天下午,我正在调试一个刚写完的配置对话框。这个对话框里有一个“确定”按钮和一个“取消”按钮,逻辑很简单,用户填好信息,点“确定”提交,点“取消”就放弃。我正美滋滋地测试着&a…

2026/7/7 23:15:47 阅读更多 →
MusePublic Art Studio效果展示:长宽比定制(4:3/16:9/1:1)生成能力

MusePublic Art Studio效果展示:长宽比定制(4:3/16:9/1:1)生成能力

MusePublic Art Studio效果展示:长宽比定制(4:3/16:9/1:1)生成能力 1. 开篇:重新定义创作边界 想象一下,你是一位设计师,需要为不同平台创作视觉内容:社交媒体需要1:1的正方形图片&#xff0c…

2026/7/5 22:48:03 阅读更多 →

最新新闻

Linux环境变量超全学习笔记|Xshell实操+命令详解+练习题完整演示

Linux环境变量超全学习笔记|Xshell实操+命令详解+练习题完整演示

一、前言 本次围绕Linux环境变量完成完整实操学习,梳理核心概念、全套操作命令,结合Xshell终端操作截图搭建完整知识体系,并完成课件配套3道实操练习题,完整记录操作流程与运行结果。 二、核心概念理解 环境变量定义 环境变量采用…

2026/7/8 7:41:25 阅读更多 →
基于群辉 + Docker + Flask 搭建企业内部自动化服务平台

基于群辉 + Docker + Flask 搭建企业内部自动化服务平台

记录一次使用群辉 NAS 搭建企业内部自动化服务平台的实践,包括 Docker 容器部署、自动更新、远程访问以及局域网设备调度。前言随着团队内部自动化需求越来越多,需要一个统一的平台来管理各种自动化流程。相比购买云服务器,群辉 NAS 具有成本…

2026/7/8 7:39:25 阅读更多 →
AKShare金融数据接口库的企业级架构设计与性能调优方案

AKShare金融数据接口库的企业级架构设计与性能调优方案

AKShare金融数据接口库的企业级架构设计与性能调优方案 【免费下载链接】akshare AKShare is an elegant and simple financial data interface library for Python, built for human beings! 开源财经数据接口库 项目地址: https://gitcode.com/gh_mirrors/aks/akshare …

2026/7/8 7:37:24 阅读更多 →
Havenlon |入门认知系列:为什么我们选择海狸作为精神符号

Havenlon |入门认知系列:为什么我们选择海狸作为精神符号

为什么我们选择海狸作为精神符号?它不代表攻击,它代表边界。摘要Havenlon 选择海狸作为精神符号,并不是因为它足够可爱,也不是想给一个严肃的安全系统套上一层轻松的外壳。真正的原因只有一个:海狸是自然界里极少见的工…

2026/7/8 7:37:24 阅读更多 →
RHCA必考的vimtutor命令深度解析:从考试准入到生产自动化

RHCA必考的vimtutor命令深度解析:从考试准入到生产自动化

1. 项目概述:为什么一个“vimtutor”命令值得单独写一篇RHCA级教程?在红帽认证架构师(RHCA)的实战现场,我见过太多人卡在同一个地方——不是不会配Ansible Playbook,不是搞不定OpenShift Operator&#xff…

2026/7/8 7:37:24 阅读更多 →
为什么KMS_VL_ALL_AIO成为Windows和Office激活的终极解决方案?

为什么KMS_VL_ALL_AIO成为Windows和Office激活的终极解决方案?

为什么KMS_VL_ALL_AIO成为Windows和Office激活的终极解决方案? 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 在数字化办公环境中,Windows操作系统和Microsoft Office套…

2026/7/8 7:35:24 阅读更多 →

日新闻

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破

3大核心能力重塑《明日方舟》游戏体验:MAA自动化助手的革命性突破 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: …

2026/7/8 0:00:48 阅读更多 →
MyBatis 批量操作深度优化——从 N+1 到批处理的全路径

MyBatis 批量操作深度优化——从 N+1 到批处理的全路径

MyBatis 批量操作深度优化——从 N1 到批处理的全路径 一、从"功能正确"到"性能可接受"——MyBatis 批量操作的三段式进化 MyBatis 在日常增删改查场景中几乎是无感的——实体映射直观、SQL 控制灵活。但当数据量从千级上升到十万级、百万级,许…

2026/7/8 0:00:48 阅读更多 →
工业负载控制方案:TPD2015FN与PIC18F45K22应用解析

工业负载控制方案:TPD2015FN与PIC18F45K22应用解析

1. 工业负载控制方案概述在工业自动化、电机驱动和照明控制等高需求场景中,可靠地控制电感和电阻负载是核心挑战之一。TPD2015FN作为东芝的8通道高端智能功率开关IC,配合PIC18F45K22微控制器,能够构建一套稳定、高效的负载控制系统。这套组合…

2026/7/8 0:02:48 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/7 14:24:45 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/7 12:34:47 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/7 15:59:06 阅读更多 →

月新闻