
直流有刷电机大概是每个搞嵌入式或者硬件的人绕不开的一个东西。不管你是做小车、做云台、做电动推杆还是拆个玩具想让它转得听话一点最后都会落到同一个问题上怎么用单片机控制它的正反转和转速。我这些年做过的电机驱动项目少说也有几十个从几块钱的L298N模块到分立MOS搭的H桥再到集成驱动芯片踩过的坑基本能写一本小册子。这篇就围绕“直流有刷电机H桥控制”这件事把原理图怎么画、PWM怎么调、DR70x这类驱动芯片怎么用从头到尾捋一遍。不管你是刚接触电机驱动的新手还是想从模块党进阶到自己画板子的老哥应该都能从里面找到点有用的东西。1. 为什么非得用H桥而不是一个三极管搞定1.1 直流有刷电机的正反转本质先把这个事说透。直流有刷电机就两根线你把正负极接对了它正转接反了它反转。听起来简单到不行但问题在于你不可能每次都手动去调换两根线。用单片机控制的时候需要的是“电子开关”来动态改变电流方向。一个三极管或者一个MOS管只能做单向导通电流只能朝一个方向流。你用它控制电机电机就只能朝一个方向转想反转没门。这时候就需要四个开关管组成一个“H”形的电路——中间横着的是电机四条竖边是四个开关这就是H桥名字的由来。H桥的核心逻辑其实就一句话对角导通。左上和右下同时开电流从左往右流过电机正转右上和左下同时开电流从右往左反转。同侧上下两个管子绝对不能同时开否则电源直接短路管子当场冒烟。这个“绝对不能”我后面还会反复强调因为它是烧板子最常见的原因没有之一。1.2 H桥的四种工作状态拆解把H桥的状态列清楚后面画图、写代码都靠这个。状态左上左下右上右下电机两端效果正转通断断通左正右负全速正转反转断通通断左负右正全速反转刹车断通断通两端接地快速停转滑行断断断断悬空惯性滑行这里有个容易被忽略的点刹车和滑行是两回事。刹车状态下电机两端被短接反电动势会让电机迅速停下来适合需要急停的场景滑行状态下电机两端悬空靠惯性慢慢停适合节能或者需要平滑减速的场景。很多新手写代码只会正转反转忽略了这两个状态结果做出来的东西要么停不下来要么停得太猛。1.3 分立方案和集成方案的取舍H桥可以用四个分立MOS管搭也可以用集成驱动芯片。我两种都用过说下各自的适用场景。分立MOS方案的好处是灵活、便宜、电流可以做得很大。你想驱动10A、20A的电机用分立MOS基本是唯一选择因为集成芯片很少有这么大电流的。但代价是外围电路复杂要加上拉电阻、栅极驱动电阻、自举电容如果用N沟道做上管、续流二极管PCB布局还得讲究不然容易震荡或者发热。集成芯片方案就省心多了像DR70x这类芯片内部已经把逻辑控制、死区时间、保护电路都做好了你只要给方向信号和PWM信号就行。缺点是电流能力有限一般几个安培以内而且芯片本身有压降会发热。我的经验是小功率、快速验证用集成芯片大功率、成本敏感、要量产用分立MOS。这篇两种都会讲到但重点放在集成芯片的实操上因为大部分人第一次做H桥用集成芯片成功率最高。2. DR70x驱动芯片到底怎么用2.1 DR70x的引脚和内部结构DR70x这个系列不同厂家后缀可能不一样但功能大同小异是一颗典型的单通道有刷电机驱动芯片内部集成了一个完整的H桥。它的引脚一般是这样分布的VCC逻辑电源通常3.3V或5V给内部逻辑电路供电VM电机电源接电池或者电源正极范围一般在2V到10V左右GND地IN1 / IN2方向控制输入两个引脚的电平组合决定正转、反转、刹车、滑行PWM有些型号单独有一个PWM引脚有些型号直接把PWM打到IN1或IN2上OUT1 / OUT2接电机的两个端子内部结构上DR70x把四个功率MOS管、栅极驱动、死区控制、过流保护、过热保护都集成在里面了。所谓“死区控制”就是芯片内部保证同侧上下管不会同时导通的那段安全时间这个时间通常是几百纳秒。你自己搭分立电路的话死区时间得靠单片机或者专用驱动芯片来保证很容易出错集成芯片帮你把这个坑填了。2.2 真值表和PWM调速的两种打法DR70x的控制逻辑用真值表表示最清楚IN1IN2PWM输出状态00X滑行悬空011反转101正转11X刹车注意这里的PWM列不同型号处理方式不一样。有的芯片PWM是独立引脚IN1和IN2只管方向PWM管调速有的芯片没有独立PWM脚你需要把PWM信号打到其中一个IN脚上。打法一独立PWM脚。IN11、IN20定方向PWM脚给方波调速。这种最干净方向和速度完全解耦代码也好写。打法二PWM打到IN脚。比如要正转调速IN1给PWM、IN2给0要反转调速IN1给0、IN2给PWM。这种打法要注意当PWM为低电平时IN10、IN20电机进入滑行状态而不是刹车。如果你想要“慢速正转”但又不希望电机在PWM低电平期间滑行这种打法就不太合适。我一般优先选带独立PWM脚的型号省心。如果手头只有不带独立PWM脚的那就用打法二但心里要清楚低电平期间电机是在滑行的。2.3 外围电路怎么配DR70x的外围电路其实很简单但有几个地方不能省。电源去耦电容。VM和GND之间一定要并一个大电容通常100uF到470uF的电解电容再加一个0.1uF的陶瓷电容。大电容吸收电机启停时的电流冲击小电容滤高频噪声。我见过太多人省掉这个电容结果电机一启动单片机就复位查半天查不出来。续流路径。虽然DR70x内部有续流二极管但如果你驱动的电机电感比较大或者PWM频率比较高建议在OUT1和OUT2之间再并一个肖特基二极管或者RC吸收电路把反电动势的能量泄放掉。这个不是必须的但能显著降低芯片发热。逻辑电源和电机电源的隔离。如果电机电源电压比较高比如12V而逻辑电源是5V建议在VCC引脚前面串一个几十欧姆的电阻再并一个稳压二极管防止电机电源的波动串到逻辑电路里。注意VM和VCC的上下电顺序有讲究。理想情况下先上VCC再上VM下电时先下VM再下VCC。如果做不到至少保证VM不会在VCC没上电的时候倒灌电流进芯片。有些型号内部有保护有些没有保险起见加个二极管。3. 从原理图到PCB的实操细节3.1 原理图绘制要点画H桥原理图的时候有几个地方我每次都会检查。第一电机两端一定要有续流路径。不管是芯片内部集成的还是外部加的原理图上要能看出来。如果用的是分立MOS每个MOS管旁边都要并一个快恢复二极管方向是源极到漏极对于N沟道。第二栅极电阻不能省。分立方案里MOS管的栅极要串一个10欧姆到100欧姆的电阻作用是限制栅极充电电流防止震荡。电阻太大会导致开关变慢、发热增加太小又起不到抑制作用。我一般用22欧姆实测比较平衡。第三自举电容。如果用N沟道MOS做上管需要自举电容来把栅极电压抬到比源极高。自举电容一般用0.1uF到1uF配合一个快恢复二极管。这个电容的容值要算假设MOS管栅极电荷是Qg自举电容Cboot要满足Cboot Qg / ΔVΔV一般取1V左右。比如Qg20nC那Cboot至少20nF实际取100nF留余量。第四电流采样。如果想做电流闭环或者过流保护可以在H桥的下管源极和地之间串一个采样电阻。采样电阻的阻值要小一般几十毫欧功率要够。比如峰值电流2A采样电阻0.1欧姆那峰值功率就是0.4W得用1W的电阻。3.2 PCB布局的坑PCB布局这块我踩过的坑比原理图多得多。大电流路径要短而粗。VM到芯片、芯片到电机、电机到地的路径走线要尽量宽。1A电流至少走40mil2A走80mil以此类推。如果走线不够宽压降大、发热严重还会引入寄生电感导致开关瞬间电压尖峰。功率地和信号地分开。电机电流在地线上产生的压降会干扰逻辑电路。正确做法是功率地和信号地单点连接通常在芯片的GND引脚附近。我一般会在PCB上留一个0欧姆电阻或者磁珠作为单点连接的位置调试的时候可以灵活处理。散热焊盘要处理好。DR70x这类芯片底部通常有一个散热焊盘必须焊到PCB的铜皮上铜皮面积越大越好最好打过孔到背面的大面积铜。如果散热焊盘虚焊芯片跑几分钟就过热保护了。去耦电容紧贴芯片。0.1uF的陶瓷电容要放在VCC引脚旁边走线越短越好。大电解电容可以稍微远一点但也不能太远。3.3 一个完整的原理图框架把上面这些串起来一个典型的DR70x驱动电路大概是这样电源部分VM接电池正极并100uF电解0.1uF陶瓷到地VCC接5V并0.1uF到地控制部分IN1、IN2、PWM接单片机IO口每个IO口可以串一个100欧姆电阻限流输出部分OUT1、OUT2接电机电机两端并一个0.1uF电容可选抑制EMI保护部分VM和VCC之间加一个二极管防止倒灌电机两端加TVS管吸收尖峰大功率场合这个框架我用了很多次基本没出过问题。当然具体参数要根据电机和电源调整但结构是通用的。4. PWM调速的核心参数怎么定4.1 PWM频率的选择PWM频率这个事选高了选低了都有问题。频率太低比如几百Hz电机会听到明显的啸叫因为人耳能听到20Hz到20kHz的声音。而且低频PWM会导致电流纹波大电机转动不平稳。频率太高比如几十kHz以上MOS管的开关损耗会增加芯片发热严重。而且高频下PCB的寄生电感和电容影响变大容易出现震荡。我的经验值有刷电机PWM频率选15kHz到25kHz。这个范围刚好在人耳听觉上限附近啸叫不明显开关损耗也可以接受。如果对噪声特别敏感可以选20kHz以上如果芯片发热严重可以降到10kHz试试。有个特殊情况如果电机电感很小比如空心杯电机电流纹波会很大这时候需要更高的PWM频率来平滑电流可能要到30kHz以上。但空心杯电机一般功率小芯片发热不是大问题。4.2 占空比和转速的关系理论上电机的转速和PWM占空比成正比。占空比50%转速就是全速的一半。但实际上不是完全线性的因为第一电机有启动死区。占空比太低的时候比如5%以下电机可能根本转不起来因为平均电压不足以克服静摩擦。这个死区大小取决于电机本身一般3%到10%。第二反电动势的影响。电机转起来之后会产生反电动势抵消一部分电源电压。所以同样的占空比空载和带载的转速不一样。第三电源电压波动。电池电压会随着放电下降同样的占空比电池满电和快没电的时候转速差很多。如果要精确控制转速最好加一个编码器做闭环。但大部分应用比如小车、风扇开环就够了知道有这些非线性因素就行。4.3 死区时间对调速的影响前面说过DR70x内部有死区控制。死区时间是指同侧上下管都关断的那段时间目的是防止直通短路。但死区时间也会影响调速性能。死区时间太长输出电压会有损失尤其是在低占空比的时候。比如死区时间500nsPWM周期50us20kHz那死区占周期的1%影响不大。但如果PWM频率很高比如100kHz周期10us死区就占了5%低占空比时输出会明显偏低。DR70x这类芯片的死区时间一般是固定的几百纳秒级别对常规应用足够了。如果你自己搭分立H桥死区时间要自己控制一般设200ns到1us。太短了有直通风险太长了输出失真。5. 代码实现从GPIO到PWM的完整流程5.1 初始化配置以常见的单片机为例控制DR70x需要配置三个引脚IN1、IN2、PWM。IN1和IN2是普通GPIOPWM是定时器输出。初始化的时候先把IN1和IN2都设成低电平让电机处于滑行状态避免上电瞬间电机乱转。PWM引脚配置成定时器PWM输出模式频率设20kHz初始占空比0。// 伪代码具体寄存器名根据芯片手册改 void motor_init(void) { // IN1, IN2 配置为推挽输出 GPIO_Init(IN1_PIN, OUTPUT_PP); GPIO_Init(IN2_PIN, OUTPUT_PP); // 初始状态滑行 GPIO_Write(IN1_PIN, 0); GPIO_Write(IN2_PIN, 0); // PWM定时器配置20kHz TIM_Config(TIM_PWM, 20000); TIM_PWM_Init(TIM_PWM, DUTY_0); }5.2 正反转和调速函数把方向控制和调速封装成函数用起来方便。void motor_set(int direction, int duty) { // duty范围0-1000对应0%-100% if (duty 0) duty 0; if (duty 1000) duty 1000; if (direction 0) { // 正转 GPIO_Write(IN1_PIN, 1); GPIO_Write(IN2_PIN, 0); TIM_PWM_SetDuty(TIM_PWM, duty); } else if (direction 0) { // 反转 GPIO_Write(IN1_PIN, 0); GPIO_Write(IN2_PIN, 1); TIM_PWM_SetDuty(TIM_PWM, duty); } else { // 停止刹车 GPIO_Write(IN1_PIN, 1); GPIO_Write(IN2_PIN, 1); TIM_PWM_SetDuty(TIM_PWM, 0); } }这里有个细节停止的时候我用的是刹车状态IN11、IN21而不是滑行。刹车停得快适合需要快速响应的场景。如果想让电机自然滑行停转把IN1和IN2都设成0就行。5.3 软启动和斜坡控制直接给100%占空比电机会猛地窜出去电流冲击也大。加一个软启动让占空比在几百毫秒内从0慢慢升到目标值体验会好很多对电机和驱动芯片也更友好。void motor_ramp(int direction, int target_duty, int step_ms) { int current 0; int step 10; // 每次增加10对应1% while (current target_duty) { current step; if (current target_duty) current target_duty; motor_set(direction, current); delay_ms(step_ms); } }step_ms设5到10毫秒比较合适太快了起不到软启动效果太慢了响应迟钝。这个斜坡控制在做小车的时候特别有用能明显减少轮子打滑和电流冲击。5.4 电流检测和保护逻辑如果硬件上有电流采样代码里可以加过流保护。思路是定时器触发ADC采样采样电阻上的电压换算成电流超过阈值就立刻关断输出。void motor_current_check(void) { int adc_val ADC_Read(CURRENT_CH); float voltage adc_val * 3.3 / 4096.0; float current voltage / SAMPLE_RESISTOR; // SAMPLE_RESISTOR单位欧姆 if (current OVER_CURRENT_THRESHOLD) { // 过流立即刹车 GPIO_Write(IN1_PIN, 1); GPIO_Write(IN2_PIN, 1); TIM_PWM_SetDuty(TIM_PWM, 0); fault_flag 1; } }这个保护逻辑要放在中断或者高频任务里响应越快越好。DR70x内部也有过流保护但那是最后一道防线软件保护能更快响应减少芯片压力。6. 常见问题排查和避坑经验6.1 电机不转或者只往一个方向转这是最常见的问题排查顺序如下先量电压。用万用表量OUT1和OUT2之间的电压正转时应该是正的反转时应该是负的。如果电压正常但电机不转那是电机的问题如果电压不对那是驱动或者控制的问题。再查控制信号。用示波器或者逻辑分析仪看IN1、IN2、PWM的波形。如果IN1和IN2的电平组合不对检查代码里的GPIO配置如果PWM没有输出检查定时器配置。最后查电源。VM电压够不够VCC有没有上电如果VM电压太低芯片可能不工作。DR70x的最低工作电压一般在2V左右但电机启动瞬间电流大电源内阻大的话电压会被拉低导致芯片复位。6.2 芯片发热严重芯片发热一般有三个原因电流太大、PWM频率太高、散热不好。先算一下电机的堵转电流。堵转电流 VM / 电机内阻。如果这个电流超过了芯片的额定电流那发热是必然的得换更大电流的芯片或者用分立MOS。如果电流在额定范围内还发热检查PWM频率。频率越高开关损耗越大试着降到10kHz看看。另外检查散热焊盘有没有焊好PCB铜皮面积够不够。还有一个容易被忽略的点续流损耗。电机电感在PWM关断期间会产生反电动势电流通过续流二极管流回电源。这个电流在二极管上产生的损耗也会让芯片发热。如果电机电感大可以考虑在电机两端并一个RC吸收电路把部分能量消耗在电阻上。6.3 电机启动时单片机复位这个问题我遇到过好几次基本都是电源问题。电机启动瞬间电流可能是额定电流的5到10倍如果电源功率不够或者去耦电容太小VM电压会瞬间跌落通过芯片内部电路影响到VCC导致单片机复位。解决办法加大VM的去耦电容至少470uF最好1000uF以上在VCC和VM之间加隔离比如用二极管或者磁珠单片机和电机驱动用独立的稳压器供电。6.4 PWM调速时电机有异响异响一般来自PWM频率落在人耳听觉范围内或者电流纹波太大导致电机振动。先把PWM频率调到20kHz以上试试。如果还有异响可能是电机本身的机械问题比如轴承磨损或者转子不平衡。另外检查PWM占空比是不是太低太低的占空比会导致电机间歇性转动发出“咔咔”声。6.5 常见问题速查表现象可能原因排查方法解决措施电机不转电源未上电量VM和VCC电压检查电源连接只往一个方向转IN1/IN2信号不对示波器看波形检查代码GPIO配置芯片发热严重电流超额定算堵转电流换大电流芯片或分立MOS单片机复位电源跌落示波器看VM波形加大去耦电容隔离供电电机异响PWM频率低调整频率调到20kHz以上调速不线性启动死区测最低启动占空比加软启动避开死区刹车太猛刹车状态确认IN1/IN2改用滑行状态7. 进阶从开环到闭环以及仿真验证7.1 编码器闭环调速开环调速的精度受电源电压、温度、负载影响很大。如果要精确控制转速需要加编码器做闭环。编码器输出脉冲单片机用定时器的编码器模式或者外部中断计数。每隔固定时间比如10ms读一次计数值算出实际转速和设定值比较用PID调整PWM占空比。PID参数整定是个经验活。我的习惯是先用纯比例控制P从0.1开始慢慢加直到转速开始震荡然后退回一点。再加积分项消除稳态误差积分时间从大到小调。微分项一般用不上除非负载变化特别快。7.2 用仿真工具验证H桥逻辑在画板子之前可以用仿真工具验证H桥的逻辑和PWM调速效果。比如用电路仿真软件搭一个H桥模型加上电机模型和PWM源看电流波形和转速响应。仿真的好处是快改参数不用焊板子。但要注意仿真模型和实际器件的差异尤其是MOS管的开关特性和电机的非线性。仿真结果只能作为参考最终还是要实测。7.3 从DR70x到分立MOS的升级路径如果DR70x的电流不够用了升级到分立MOS是必然的。升级的时候注意几点上管用P沟道还是N沟道P沟道简单不需要自举但导通电阻大、价格贵、选择少。N沟道导通电阻小、便宜但需要自举或者专用栅极驱动芯片。大电流场合基本都用N沟道加自举。栅极驱动芯片怎么选看驱动电流和耐压。驱动电流要足够大保证MOS管快速开关耐压要高于VM电压。常见的有半桥驱动芯片一片驱动一个桥臂两片组成H桥。死区时间怎么设分立方案的死区时间由单片机或者驱动芯片控制。单片机控制的话在换向的时候先关断所有管子延时几百纳秒再开通新的管子。这个延时可以用定时器实现也可以用驱动芯片自带的死区控制。8. 一些零散但重要的经验8.1 电机两端并电容的讲究电机两端并一个0.1uF的陶瓷电容能有效抑制电刷火花产生的EMI。但电容不能太大太大了会增加开关损耗还会和电机电感形成LC振荡。0.1uF是个比较安全的取值。如果EMI要求严格还可以在电机两端各串一个磁珠再并电容组成π型滤波。磁珠选高频阻抗大的比如100MHz时阻抗100欧姆以上。8.2 电源反接保护电池反接是新手最容易犯的错误之一。轻则芯片烧毁重则电池爆炸。最简单的保护是在VM回路串一个二极管但二极管有压降大电流时损耗大。更好的方案是用P沟道MOS做理想二极管压降小但电路复杂一点。如果成本允许建议加反接保护。我见过太多因为电池接反烧板子的案例加一个二极管就能避免性价比很高。8.3 上电顺序和使能控制有些应用需要控制电机的上电顺序比如先让单片机初始化完成再使能电机驱动。这时候可以在VM回路上加一个使能开关用MOS管控制。单片机初始化完成后拉高使能引脚电机驱动才上电。这个做法还能实现低功耗待机。不用电机的时候把VM切断芯片完全不耗电。对于电池供电的设备这个功能很实用。8.4 调试用的假负载调试H桥的时候不要一上来就接电机。先用一个功率电阻或者灯泡做假负载确认控制逻辑和PWM输出正常再接电机。电机是感性负载出问题的时候电流冲击大容易烧东西。假负载是纯阻性安全得多。我一般用一个12V的汽车灯泡做假负载既能看出PWM调速的效果灯泡亮度变化又能限制电流。确认没问题了再换电机。8.5 示波器看波形的技巧调试H桥示波器是必备的。看波形的时候注意几点测OUT1和OUT2的时候用差分探头或者两个探头相减不要直接把探头地夹在OUT上否则可能短路。看PWM波形的时候触发方式选边沿触发时间基准调到能看清一个完整周期。重点看上升沿和下降沿有没有震荡如果有说明栅极电阻或者布局有问题。看电流波形的话用电流探头或者采样电阻上的电压。电流波形能反映很多问题比如续流是否正常、有没有直通、电机是否堵转。9. 写在最后的一些个人体会做电机驱动这些年最大的感受就是理论很简单实操全是坑。H桥的原理十分钟就能讲明白但真正画板子、写代码、调试的时候电源、布局、散热、保护每一个环节都能让你卡半天。DR70x这类集成芯片大大降低了入门门槛让新手不用一上来就面对分立MOS的复杂性。但集成芯片不是万能的电流有限、散热有限用到一定程度就得升级。升级到分立方案的时候前面集成芯片积累的经验——比如PWM频率怎么选、死区时间怎么设、续流路径怎么走——都是有用的。最后分享一个我自己的习惯每次做新的电机驱动板第一版一定留足够的测试点和跳线。测试点方便量波形跳线方便改电路。不要想着一次做完美留点余地调试的时候会感谢自己。还有手边常备几个不同规格的电机和假负载。调试的时候换着试能快速定位是驱动的问题还是电机的问题。这个习惯帮我省了很多时间。