
说实话我第一次做无刷电机PWM控制时也被“50Hz”这个参数坑过。手里拿着一台直流无刷电机想用STM32F103RCT6输出PWM控制转速结果写代码时直接把定时器配成50Hz、占空比50%输出电机不但不转还带着啸叫MOS管烫得能煎鸡蛋。后来才搞明白50Hz是遥控器、电调之间“油门信号”的刷新率而真正驱动无刷电机三相桥臂的PWM频率一般要10kHz以上。这篇博文就从这两个频率的区别讲起把50Hz频率选择、占空比怎么调、MOS管发热、电机飞车、PWM故障保护这些实战问题一次说清楚。适合刚接触无刷电机驱动的同学也适合已经调过有刷电机、想切到无刷场景的工程师参考。1. 无刷电机PWM控制的基本逻辑1.1 无刷电机为什么离不开PWM无刷电机和有刷电机的最大区别是“没有碳刷换向”转子上的磁场必须靠外部电路主动切换。最简单的三相无刷电机内部有A、B、C三相绕组转子是永磁体。要让转子持续转起来就得按顺序给绕组通电形成旋转磁场。这个顺序一般叫“六步换相”或“方波驱动”一个通电周期分六个状态每个状态让两个桥臂导通剩下一个悬空。但只给绕组通恒压电是不行的转速没法精细控制而且启动瞬间冲击电流非常大。用PWM来做才是常见的方案。PWM在这个场景里干了两件事一是通过改变占空比来改变绕组平均电压从而控制转速和力矩二是配合换相顺序让不同相的MOS管按一定时序开关。所以说无刷电机驱动里PWM不是单独一个开关信号而是一整套和换相逻辑绑在一起的调制策略。哪怕是更高级的FOC驱动底层输出到三相桥臂的也仍然是PWM只是占空比的计算方式从六步换相变成了SVPWM或正弦波调制。我见过不少从有刷电机转过来的新手习惯把电机当成一个“纯电阻负载”一个PWM通道接到MOS栅极上就开始调占空比。对无刷电机来说这样是不够的。你至少要清楚当前转子位置、该导通哪两个桥臂、PWM加在上桥还是下桥、换相点怎么处理。搞明白了这些再看频率和占空比才不会迷糊。1.2 控制信号频率和驱动频率是两回事这是个特别容易踩坑的概念。你打开电调说明书写着“输入信号频率50Hz-500Hz脉宽1-2ms”有些同学就把STM32定时器配成50Hz然后直接接MOS管全桥。结果电机鬼哭狼嚎转速一顿一顿的。实际上电调说明书里的“输入信号频率”指的是控制信号也就是接收机通道或者控制器发给电调的油门信号。它决定的是“你希望电机转多快”这个指令多久更新一次。而电调内部输出到MOS管的PWM驱动频率才是真正决定电机绕组电流连续性的斩波频率。这两个频率差了三个数量级完全不是一个东西。我习惯用一个很糙但好懂的类比控制信号频率像是老板催活的频率老板每秒说50次“快点/慢点”听起来已经很频繁了但真正干活的工人手里的锤子每秒得敲两万下力气才能均匀地传下去不然活儿会一块一块的噪声也大。无刷电机绕组是有电感的电感有“惯性”电流变化需要时间。如果驱动频率太低比如50Hz在MOS管关断期间电感续流完了电流就掉到零等下次导通再重新爬升平均力矩大幅下降还会产生严重的高频噪声和啸叫。效率低不说MOS管也容易过热。所以你要先问问自己我写的这个PWM是给电调的控制信号还是直接给MOS桥的驱动信号如果用的是现成电调你要做的是生成50Hz或更高刷新率的控制PWM如果自己做驱动板MOS管栅极PWM请直接上10kHz以上。2. 50Hz频率选择的来龙去脉2.1 为什么RC设备默认是50Hz很多玩航模、车模的朋友第一次接触无刷电调都是从遥控器接收机油门通道开始的。接收机输出到电调的PWM信号行业默认就是20ms周期、1-2ms高电平脉宽也就是50Hz刷新率、5%-10%占空比。这个标准是从模拟舵机时代留下来的早期的模拟舵机用50Hz刷新率更新角度指令1ms对应一边最大1.5ms对应中位2ms对应另一边最大。电调为了兼容这套遥控系统直接沿用了相同的脉宽标准。所以你能看到电调上经常会有一个三线插头信号线接到接收机的CH1或者CH2。PWM input on ch1这个说法在飞控、接收机调试里非常常见意思就是第一个通道的PWM输入。它对高电平时间很敏感1.0-2.0ms之外基本就被当成异常信号处理了。这个标准的好处是兼容性好几乎任何遥控器都能和任何电调配对但坏处是50Hz刷新率对现代高速应用来说有点慢相当于每20ms才更新一次转速指令电机响应自然不够跟手。2.2 可不可以改成100Hz、200Hz甚至更高可以而且现代数字电调基本都支持更高的控制信号刷新率。我的做法是先查电调说明书看它支持的最高刷新率是多少。比如很多中高端航模电调支持250Hz甚至500Hz脉宽范围仍然是1-2ms。把刷新率从50Hz提高到250Hz相当于转速指令每4ms更新一次延迟明显减小四轴、穿越机这类对响应要求高的场合非常讲究这个参数。如果你自己用STM32F103RCT6做控制器不接遥控器而是直接输出PWM控制电调那么完全可以不局限于50Hz。比如你用定时器TIM2输出一个200Hz、周期5ms的PWM高电平时间依然控制在1-2ms对应最小、最大转速。需要注意的是电调对信号频率有一个容忍范围超出范围会触发失控保护甚至直接不响应。所以改频率前最好先用信号发生器或者单片机实测一下电调是否正常。这里还有个细节控制信号PWM的占空比虽然只有5%-10%但调参时不要按百分比去理解。电调真正识别的是高电平时间单位是us或ms。1ms油门最低2ms油门最高而不是5%对应最低、10%对应最高。所以你在写代码时应该直接设置比较寄存器让高电平时间在1000us到2000us之间变化别管周期是20ms还是5ms。2.3 STM32F103RCT6怎么生成合适的控制信号以最常用的STM32F103RCT6为例假设系统时钟72MHz用TIM2的通道1输出PWM。想生成50Hz控制信号也就是周期20ms可以设置预分频器PSC719这样定时器计数时钟变成100kHz再设置自动重装值ARR1999这样溢出周期就是20ms。高电平脉宽1ms时比较值CCR100脉宽2ms时CCR200。如果你想用200Hz刷新率周期就是5msARR改成499CCR依然是100到200这个范围。你看出来没有改变刷新率只改ARR不改CCR范围。这就是为什么我说占空比百分比会骗人同样是10%占空比50Hz下是2ms脉宽200Hz下是0.5ms脉宽电调很可能把0.5ms当成关闭信号。所以调参时永远盯着高电平时间不要只盯占空比。用CubeMX配置也很简单选择TIM2PWM Generation CH1设置PSC、ARR和初始Pulse。生成代码后通过修改__HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, pulseValue)来动态改变脉宽。如果项目里要用PWM input采集遥控器信号那还要配置另一个定时器的输入捕获模式在CH1上测高电平时间然后映射到你的目标转速。我习惯把采集到的us值和目标脉宽直接做线性映射最后加一个限幅和斜率限制防止转速突变。3. 占空比调参的核心技巧3.1 占空比、等效电压和电机转速的关系对电机绕组来说PWM的平均电压约等于母线电压乘以占空比比如12V母线、50%占空比理想情况下绕组平均电压约6V。但实际还要减去MOS管导通压降、死区时间内续流二级管的压降以及线路电阻损耗。占空比越低这些损耗占比越高所以你会发现小占空比时电机线性度很差可能20%占空比电机还是纹丝不动超过25%突然开始转。如果前面接了电调那事情又不一样。你给电调的控制PWM占空比和电机实际电压并不直接线性对应因为电调内部有自己的驱动策略有些电调在低油门段做过映射处理让起步更柔和。所以调参时不要拿“占空比50%就是半速”这种想法去套。更好的方法是直接测转速或反电动势把控制脉宽和实际转速做成一张表再决定曲线怎么补偿。3.2 油门行程校准最大最小脉宽先对齐接电调之后第一件事不是调占空比而是做油门行程校准。这一步很多玩DIY的新手会跳过结果出现“油门推不到底”“最小油门电机还在转”之类的问题。校准逻辑很简单让电调知道你的控制器或遥控器发出的最小脉宽和最大脉宽分别是多少。我的做法是先给电调上电在听到提示音后把PWM调到最大脉宽比如2000us再调到最小脉宽比如1000us电调会记录这两个边界。不同电调具体的进入时序不一样有些是先最大后最小有些是先最小后最大一定要看说明书。校准完成后电调内部会把这组边界作为0%和100%油门之后你发送被校准范围内的脉宽电机速度响应才是准的。如果自己写代码我建议把校准参数存到Flash里。每次上电先读取保存的最小、最大脉宽并加一个保护逻辑如果收到的脉宽超过边界超过5%就按边界值钳位。这样能避免调试时误发异常PWM导致电机飞车。3.3 启动、堵转和限流时的占空比策略无刷电机最怕的一种情况是堵转时还往上加占空比。电机不转绕组相当于纯电阻电流会瞬间飙升MOS管和电机都会过热。带霍尔传感器的三相无刷电机可以用霍尔信号判断转子位置和是否失步正常换相时霍尔状态按固定顺序变化如果某个状态持续太久说明转子没跟上这时应该立刻降低PWM占空比而不是继续增大。启动阶段我也建议用小占空比试探。比如六步换相驱动先给一个10%-15%的占空比同时检测霍尔状态是否在几毫秒内变化如果没变化给一个小的位置扰动再不行就报错。这样一来可以避免启动瞬间冲击力矩过大也能提前发现霍尔接线是否错误。对反电动势检测的方波驱动启动更依赖预定位和强制换相占空比更不能给大否则大概率原地抖动然后过流。过流保护一定要硬件化不能只靠代码if判断。我常用的方法是在下桥母线串采样电阻经过比较器后接到STM32定时器的刹车输入BKIN。一旦电流超过阈值PWM输出被硬件强制拉低占空比再怎么调都输出不了这样才能真正保护功率级。这也就是所谓“PWM故障保护”的核心作用它不是一个软件标志位而是一条独立的硬件关断通道。4. 实操中绕不开的坑4.1 PWM接MOS管发热先查死区和驱动能力这大概是后台被问得最多的问题“我把PWM接上去什么都没动MOS管就烫手。”如果你确定占空比不高、电机也没有堵转那问题多半出在驱动电路和死区设置上。无刷电机三相桥用的是上下桥臂互补输出上管开、下管关反之亦然。如果上下管切换太慢或死区太小就会出现一瞬间两个管子同时导通母线直接短路电流大得可怕。这种发热是“迅速升温”式的几秒钟就能冒烟。解决办法是检查死区时间STM32F103的高级定时器TIM1和TIM8可以配置死区我一般从1us开始试根据MOS管栅极电荷量调整。栅极驱动电阻也要注意电阻太大会让开关边沿变缓损耗增加太小会引起振铃。很多集成MOS驱动的无刷电机控制MCU内部已经做了死区管理但外部预驱方案就得自己留意。另外就是开关损耗。PWM频率越高MOS管开关次数越多开关损耗越大。如果电机电感比较大电流纹波本来就小可以适当降低驱动频率到16kHz或12kHz如果电感很小那就需要更高频率来限制电流纹波此时必须选择开关损耗更低的MOS管并加大散热面积不能只怪频率。4.2 电机飞车和PWM故障保护“飞车”这个词听起来有点吓人但做无刷驱动确实会遇到。现象是电机突然以最高速度狂转控制信号好像失灵了。原因可能有三类一是霍尔信号断线或接线错序MCU根据错误的转子位置输出错误的换相状态电机会乱抖甚至加速二是控制PWM信号的线缆受干扰电调收到异常高电平脉宽直接输出最大油门三是程序里启动时SC油门状态判断错了上电瞬间把占空比拉满。不管哪种情况第一道防线都是故障保护。用STM32的时候我会把刹车输入作为最高优先级任何软件异常、霍尔错误、过流信号都映射到BKIN上让PWM立即停止。同时油门信号只要有超过2000us的脉宽持续超过一定时间就认为是异常信号进入失控保护状态输出0%油门。电调本身的失控保护逻辑也是这样做的但自己做控制器时千万别省。霍尔信号异常检测也很重要。正常带霍尔三相无刷电机霍尔传感器六个状态会按固定顺序循环。我在代码里加了一个状态机校验如果跳变顺序不对比如从状态1直接跳到状态4说明霍尔接线有问题或转子失步立刻封锁PWM。这个逻辑写起来很简单但能避免很多炸MOS管的事故。4.3 常见问题速查表我把实际调试中碰到过的问题整理成一张表方便排查现象可能原因排查/解决办法电机不转但PWM有输出换相顺序错误或控制脉宽低于启动阈值检查霍尔状态顺序逐步提高脉宽到1.2ms以上电机啸叫严重驱动PWM频率太低如50Hz把MOS管驱动频率提高到16kHz以上MOS管迅速发热死区过小/驱动电阻不合适加大死区时间调整栅极电阻测上下管波形电机转速忽高忽低控制PWM刷新率太低或信号抖动提高控制信号频率到100Hz以上加输入滤波上电直接全速转油门行程未校准或PWM引脚默认高电平做油门行程校准初始化为最低脉宽并拉低堵转后烧MOS管过流保护不及时增加硬件比较器和BKIN刹车输入霍尔信号错误导致飞车接线错序或线缆干扰确认霍尔状态表加信号滤波异常时封锁PWM这张表不是万能但能覆盖八成的新手问题。我自己的习惯是先看电源电流再看波形最后才怀疑代码逻辑。很多时候问题并不是算法复杂而是最简单的信号没对。5. 从CubeMX到实测的流水账经验最后分享一点我这几年调试无刷电机的流水账经验。我用STM32F103RCT6做的第一版无刷驱动CubeMX配好TIM1的互补PWM和死区TIM2做控制信号输入捕获TIM3做霍尔信号采集。配置完成后第一件事不是接电机而是拿示波器看六个MOS管栅极波形确认上下管没有直通确认频率、死区、占空比都符合预期。这一步能救命的毕竟如果硬件有直通风险接上电机就是要烧东西的。确认波形没问题后我再接一个低压小功率电机母线电压先降到5V左右用最保守的参数测试。启动占空比从8%开始每200ms加1%观察霍尔波形是否正常切换。如果电机在某个点停转或抖动我会停下来查霍尔状态而不是继续加大占空比。调通一个电机之后我再逐步提高母线电压、加大负载每一步都用电流探头观测确保没有异常冲击。整套流程走下来我最大的体会是无刷电机PWM控制的技术点其实并不复杂难的是对频率和占空比这两个参数的敬畏。控制信号频率和驱动信号频率必须分开设占空比要对应到真正的高电平时间而不是单纯的百分比每次只能改一个参数改完看现象再改下一个。踩过几次坑之后我现在写代码都会在初始化阶段把PWM输出强制拉到最低脉宽加一个延迟确认系统就绪后才进入正常控制。这个小习惯帮我避免了好几次上电飞车也建议你试试。