尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PWM实战指南:从LED呼吸灯到直流电机调速的原理与配置

PWM实战指南:从LED呼吸灯到直流电机调速的原理与配置 PWM这个词玩单片机的人迟早会撞上。你可能已经见过某个例程里写了PWM然后把信号接到一颗LED上发现LED确实变暗了再接上一个直流电机电机也确实转慢了。但很多人到这里就停了——能调这个结论有了为什么能调却没想明白。这篇内容想做的就是把LED亮度和电机转速这两件事从同一个PWM原理上打通再把频率、占空比、定时器配置、驱动电路这些实操细节串起来让你下次拿到一个调亮度、调转速的需求时心里是有底气的而不是照抄一段配置了事。先说清楚它能解决什么问题所有让能量连续可变的需求小到LED呼吸灯大到直流电机调速、伺服控制、开关电源调压底层几乎都是PWM。这篇文章从原理讲到实战再讲到我踩过的坑适合刚学会单片机GPIO输出、正准备接触PWM以及已经能调出波形、但还说不清参数之间关系的人。看完你可以自己从零配一个PWM输出也能判断为什么某个电机会尖叫、为什么LED在闪。1. PWM的本质一张一合之间藏着平均值1.1 为什么一盏快速闪烁的灯看起来像变暗了先回忆一个最基础的场景你手里有一颗LED接在单片机的某个引脚上。写一段代码让它一亮一灭地闪频率大约每秒10次10Hz肉眼能清清楚楚看到闪烁。现在把闪烁的间隔不断缩短缩短到每秒1000次甚至上万次你会发现眼睛已经分不清它灭掉的那一瞬间了。这个现象背后有两个关键机制。第一是人眼的视觉暂留效应视觉系统对光亮度的感受本质上是在按时间累计光能量当LED在一个周期内只点亮一部分时间眼睛在单位时间内接受到的总光能量恰好等于同一颗LED以较低亮度持续点亮所给出的能量。第二是视觉处理本身有惯性所以高频闪烁会被融合成连续的稳定画面。于是PWM调LED亮度本质不是真的改变了LED的供电电压而是用时间换能量把总发光量摊薄了。这里有个细节值得强调视觉暂留并不能让所有频率都不闪。频率太低比如小于50到60Hz你仍然会感到明显闪烁而且长时间看眼睛容易疲劳。频率足够高之后常见做法取1kHz以上就完全察觉不到闪了。我试过用几百Hz的PWM调一个普通白光LED即使在明亮环境下余光也能捕捉到颤动调到1kHz以上才彻底干净。所以对LED来说频率不是越高越好而是至少要越过人眼敏感区。1.2 占空比和频率PWM的两个旋钮讲到PWM有两个数字无论如何绕不开占空比和频率。占空比Duty Cycle是高电平时间占整个周期的百分比。假设一个PWM波形周期为T高电平时间为ton那么占空比D ton / T × 100%。占空比决定能量给多少——对LED占空比越大平均亮度越高对电机占空比越大等效电压越大转速越高。频率Frequency是1秒内重复多少个周期f 1/T。频率决定切换多快——对LED要让闪烁感消失对电机频率直接影响噪声、损耗和转速稳定性。占空比和频率是两个互相独立又不可分割的参数工程上要分别根据负载去选不能只盯一个。打个比方可能更好理解。假设你在给泳池装水但水龙头只有全开和全关两个状态。PWM就是不停地把水龙头开到最大、再关上、再开到最大。你把每10秒里开5秒那水池水位上升的速率约等于全开速率的一半。这里的开5秒、关5秒就是占空比每10秒一轮回就对应频率。这个比喻虽然粗但它抓住了PWM的本质我们并不是在连续调节而是在快速切换靠被控对象自身的惯性——视觉暂留、电感的储能效应——把一高一低的脉冲抹平成平均值。原理部分讲透很重要因为后面所有调LED、调电机的操作说到底都在调整占空比和频率这两个旋钮。理解了这两个旋钮你才能理解为什么配置定时器时要同时看重载值和比较值也才能明白示波器上那串方波到底意味着什么。2. 从LED到直流电机为什么同一个办法能通吃2.1 LED要的是平均电流电机要的是等效电压回到标题的问题为什么PWM既能调LED亮度又能调直流电机转速答案其实分两半。LED本质上是一个电流型器件亮度基本由流过它的正向电流决定在额定范围内近似线性。当你把PWM方波送给LED通过限流电阻后它的导通和关断非常干脆高电平期间电流到设定值LED满亮低电平期间电流为零LED灭。在整个PWM周期内平均下来的电流只有满亮时的占空比百分比于是发光能量按比例下降亮度就变了。直流电机不一样它是一个感性负载。感性元件有个重要性质电流不会突变。当电机两端加上方波电压在导通时间里绕组电流逐渐上升在关断时间里电感会继续推动电流流动通过续流回路而不是立刻归零。所以电机绕组里的电流是连续的、带有一定纹波的。这个连续电流在电机内产生转矩并决定转速而PWM方波电压的等效值约等于供电电压乘以占空比于是电机得到的平均电压被降低转速降下来了。这里有个微妙的点值得想一下LED严格跟随PWM的亮/灭逻辑靠视觉暂留去脑补平均值直流电机则因为电感的惯性电流本身就被平滑了不需要人去脑补平均值。换句话说LED是靠人眼惯性来假的平滑电机是电感在真的平滑。2.2 为什么不用调电压或者串个电阻调速接下来你可能会问既然最终效果都是降低有效值为什么不直接把电压调低或者串一个可调电阻调电压的方案确实存在但代价很大。稳压芯片的调整范围有限效率低对电机这种大电流负载线性调整方式那部分多出来的电压几乎全部变成调整管上的热量。PWM的好处在于开关管工作在饱和导通和完全截止两个状态这两种状态的损耗都极小不像线性方式把多余的电压烧在调整管上。用PWM调速系统整体效率非常高这是它被普遍采用的根本原因。串电阻调速更糟糕。电阻上白白消耗电能发热严重而且负载一旦变化转速受影响极大电机的电磁转矩和端电压直接挂钩串了电阻低速时带载能力会被严重削弱。PWM调速由于始终给电机的只是全电压的脉冲电机的峰值转矩能力没被人为削掉低速带载能力远好于串电阻方案。这也是为什么工业上几乎所有直流电机调速底层都是PWM。所以你得养成一个习惯看到调亮度、调转速这类需求第一反应不是把电压拧小一点而是占空比给多少。PWM本质上把能量控制这个目标拆成了两个简单的数字占空比和频率。3. 单片机怎么输出PWM软件模拟和硬件外设两条路3.1 软件模拟用延时和GPIO翻转硬挤PWM最容易想到的实现方式就是写代码让引脚置高、延时、置低、延时。对LED这种不需要太高频率、精度要求也不高的场景软件模拟足够用代码大概是while(1) { GPIO_SetHigh(LED_PIN); delay_us(500); // 高电平持续500us GPIO_SetLow(LED_PIN); delay_us(500); // 低电平持续500us }这段代码产生一个1kHz周期1ms的PWM占空比50%。软件模拟的好处是灵活、不挑芯片任何能翻转GPIO的单片机都能做坏处也明显CPU被占住了延时期间什么活都干不了。而且占空比一旦要动态变化你得反复修改延时时间实时性非常差。所以软件模拟更适合教学示例和对并发没要求的场景正经产品里很少用它做主回路。3.2 硬件PWM外设让定时器自己去翻转引脚真正实用的是单片机自带的硬件PWM外设。原理并不复杂定时器不断向上计数当计数值小于某个比较值时输出高电平计数值大于等于比较值时输出低电平或者反过来取决于用的是PWM模式1还是模式2。定时器自动翻转引脚CPU完全不用管——这就是硬件PWM的底层逻辑。以STM32为例一套标准配置流程是配置定时器时钟设置预分频器PSC和自动重载值ARR得到目标频率再设置比较寄存器CCR控制占空比最后把定时器通道引脚复用成PWM输出。如果你用STM32CubeMX点几下鼠标就能生成初始化代码比手写寄存器快得多。但真想理解参数背后的关系还是要知道ARR、PSC和CCR怎么算。硬件PWM的优势在于波形由定时器硬件自动产生抖动极小、频率稳定而且不占CPU时间。你可以让定时器后台一直输出一个占空比精确的方波同时CPU去处理按键、屏幕、通信这在软件模拟下几乎无法舒服地做到。3.3 频率、占空比的计算方法ARR、PSC和CCR的关系给一个可以直接套用的计算框架很多人都是在这里绕晕的。定时器的输入时钟先经过预分频器PSC分频得到计数时钟。计数频率 定时器时钟 / (PSC 1)。定时器向上计数从0数到ARR时一个周期结束总共数了 (ARR 1) 次。因此PWM频率f 定时器时钟 / [(PSC 1) × (ARR 1)]占空比由CCR决定因为每周期中CCR对应了高低电平翻转的时刻。占空比 CCR / (ARR 1) × 100%。举个例子。STM32F103的定时器时钟为72MHz我想要1kHz的PWM同时希望占空比调节粒度细腻一些。先选PSC 71得到计数频率 72MHz / 72 1MHz也就是每微秒计一次数。再选ARR 999那么PWM频率 1MHz / 1000 1kHz。如果我要60%占空比CCR设为600即可。这样占空比的理论分辨率是1/1000对应0.1%对绝大多数应用足够。这套公式在不同单片机上写法略有差异但本质一样先定频率再定分辨率最后换算成寄存器值。在STC、GD32、STM32上遇到PWM频率不对的Bug十有八九是PSC或ARR那边的加减1搞反了不是公式问题。4. 实操从呼吸灯到直流电机一点一点把它转起来4.1 呼吸灯实测频率、占空比的节奏怎么选先做一个最直观的实验呼吸灯。效果是LED从暗到亮、再从亮到暗像缓慢呼吸一样。实现思路很简单PWM频率固定比如1kHz周期性地改变占空比从0%缓慢增大到100%再缓慢减小到0%。呼吸周期通常取2到3秒太短显得急促太长又失去柔和感。具体到代码里主循环每隔十几毫秒把CCR加一步等CCR到ARR后再开始递减。步长大小直接决定细腻程度步长太大亮度变化是跳变的能看到台阶步长越小越平滑但可能感觉太慢。我实践中一般把一次完整呼吸分200到300步每步间隔10到20ms视觉效果比较自然。做这个实验时顺便记住一个现象占空比从0%增加到100%的过程中LED亮度在低占空比区域的变化似乎比高占空比区域更明显这是正常的因为人眼对低亮度变化更敏感而且LED亮度曲线本身并非完全线性。所以你在做亮度百分比映射时不用为非线性焦虑真要考虑线性观感可以做Gamma校正但初学者先不用管。4.2 从LED到电机驱动电路这道坎现在进入重头戏把PWM接到直流电机上让转速跟着占空比走。这里有一个很多人栽过的跟头单片机的GPIO引脚只能输出几毫安到二十毫安级别的电流而一个普通小电机启动时可能要吃几百毫安甚至几安。直接拿GPIO去接电机轻则电机不转重则烧掉单片机引脚。所以电机必须通过功率驱动级来接PWM。最基础的方式是一颗三极管或MOSFET做开关。用N沟道MOSFET举例PWM从栅极输入源极接地漏极接电机负极电机正极接电源正极。PWM高电平时管子导通电机得电PWM低电平时管子截止电机断电。注意电机是感性负载断电瞬间会产生反向感应电动势必须在电机两端反向并联一个续流二极管阴极接电源正极阳极接电机负端。不然这个反向电动势有概率击穿管子。这一点真不是理论上的建议而是实践中的必须我见过不止一块板子因为漏了这个二极管MOS管换了好几个。还需要提醒一句话即便你用的是51单片机也常听人说驱动LED时不要用输出高电平的方式。原因是很多51单片机的端口高电平拉电流能力弱、低电平灌电流能力强于是LED常常采用低电平点亮接法。这和PWM无关但要提醒你算限流电阻时先确认引脚在满占空比时到底能供出多少电流否则会发现占空比100%时LED依然不够亮。关于驱动芯片现在市面上还有很多集成方案比如LED驱动器芯片或者电机驱动芯片不少还引出了FB脚和CS脚用设定电流。它是把恒流电路和功率开关集成到一颗IC里你用外部PWM给一个调光/调速引脚占空比变化就能控制输出功率省掉自己搭功率管的麻烦。原理和我们讲的单片机PWM并没冲突只是换了一级执行器。4.3 电机驱动电路到底该怎么接两种实战方案对照给两个可以直接抄作业的方案。方案一NPN三极管适合小电流电机比如5V玩具电机。电路连接如下GPIO经一个1kΩ电阻接NPN的基极发射极接地集电极接电机负极电机正极接电源正极。电机两端反向并联续流二极管。这种方案开关速度受限于三极管驱动和工艺PWM频率不宜太高5kHz以下比较稳。方案二N沟道MOSFET适合中大电流电机也是主流选择。电路连接GPIO通过驱动电阻接MOSFET栅极源极接地漏极接电机负极电机正极接电源正极。MOSFET需要足够的栅源电压Vgs才能完全导通。如果你的单片机是3.3V或5V供电很多逻辑电平MOS可以直驱但型号必须选对Vgs不够的话MOS会工作在线性区而不是开关区发热会特别明显。选型核心顺序先看电机的额定电流和堵转电流再选开关管再算基极或栅极电阻最后才写程序。我早期调一个小直流电机板子其余部分全对就是选的MOS管Vgs阈值太高栅极5V驱动时没完全导通管子烫得能闻到焦味换成逻辑电平MOS比如AO3400、IRLZ44N这类立刻正常了。所以说器件选型这个问题在任何单片机教程里都不该只是不起眼的一句话。5. 踩坑实录LED闪烁、电机啸叫和波形检查5.1 为什么LED看着总在闪亮度到一半就没变化了一个很典型的问题我PWM频率设置成200Hz占空比从0到100LED前一半亮度变化挺明显后一半几乎没变化。这里至少踩了两个坑。第一个坑是频率不够。200Hz虽然高于人眼看到频闪融合的临界值附近但依然处于边缘敏感区尤其用余光看LED或者周围灯光较强时很容易捕捉到闪烁感。把频率提到2kHz以上基本就不会再觉得闪了。第二个坑是亮度在小占空比区段变化不明显这跟LED光电特性和人眼感知都有关系属于正常现象。如果你需要看起来线性的效果做Gamma映射会更好而不是怀疑参数算错了。还有一种亮度死活上不去的情况不是PWM的问题而是LED的限流电阻选太大了。要注意限流电阻应该按高电平完全导通时允许的最大电流来算而不是按平均电流算。很多人用平均电流去选电阻结果占空比高时电流一直被压着LED到不了最大的理论亮度。这是一个很典型的软件对、硬件错案例。5.2 电机不转、转不停、有尖叫频率和驱动的双重困境电机场景的坑更热闹。先说电机不转占空比已经给到50%以上还不能启动大概率是PWM频率太高加上驱动电路的开关速度跟不上每个脉冲还没让电机电流上升到足以克服静摩擦脉冲就结束了。解决方向有两个降低PWM频率有的小电机500Hz到2kHz就很舒服或者改善驱动电路的开关能力。很多入门教程默认拿LED的10kHz PWM去驱动电机结果转不动那不是电压不够而是切换节奏没对上。再聊电机尖叫。这个声音不是电机故障声而是PWM频率恰好落在人耳听觉范围内电机绕组在磁场力和机械振动下发出了可听噪声。尤其在2kHz到10kHz区间人耳非常敏感听起来就十分刺耳。解决办法其实两句话把频率调到20kHz以上让人耳听不见或者把频率降到几百Hz让噪声变得低沉但随之而来的是电流纹波变大、转速相对不稳需要做取舍。不同电机的甜蜜点不同我常用的方法是把PWM频率从500Hz开始往上扫同时用耳朵听找到最安静、转速又稳定的区间固定下来。还有一个跟驱动芯片相关的坑H桥驱动芯片如果同时导通上桥和下桥会直接短路炸管。正因为这个原因很多驱动芯片要求程序里设置死区时间。如果你用分立元件搭H桥这件事比想象中更重要死区时间设置表通常可以在芯片手册里找到不建议省略。5.3 用示波器看PWM波形占空比到底是不是你以为的那个纸上谈兵容易出错示波器才是PWM调试真正的照妖镜。把探头接到PWM输出引脚你应当看到一串整齐的方波。用示波器的Measure功能直接测频率和占空比先确认它们和你的配置一致然后再继续下一步。有几个细节要注意。第一探头的接地夹要尽量短接到测试点附近的地接地引线拉得太长与信号之间形成一个大的环路你会在方波边缘看到明显振铃那未必是电路问题更可能是测量方法引出的寄生电感。第二示波器带宽不需要太高但采样率要够普通100MHz带宽的示波器完全够用。第三示波器量电机两端时波形可能不是整齐的方波——电机是感性负载断电瞬间的反电动势会把波形顶出一个尖峰这正是续流二极管起作用的表现如果尖峰异常高先查二极管有没有接反或者漏接。第四PWM模式1和模式2的区别对输出波形就是有效电平出现的时间段不同如果你要用这个PWM信号去触发外部逻辑选错模式会产生奇怪的时序问题这也是很多人反复调不出预期效果的隐藏原因。关于PWM的负载保护我还想说一句很多带PWM外设的单片机有故障保护输入功能外部信号能强制PWM输出进入安全状态。如果你发现PWM莫名其妙的没有输出先去查相关故障标志位而不是马上怀疑寄存器配错。这一点在电机驱动和电源类应用里尤其常见。到这里PWM这条线从为什么到怎么做再到现在已经完整走了一遍。我个人现在的做法是接到一个PWM调速需求先问两件事——负载是LED类还是电机类决定频率落在哪个区间然后问是开环控制还是闭环控制开环就直接码占空比闭环再考虑加PID。至于占空比能做到多细致看定时器分辨率看开关管的开关损耗看系统噪音要求这几项都满足后剩下的余量才是你的操作窗口。最后送你一个小技巧手头暂时没有示波器又想快速判断PWM频率合不合适用LED做简易指示器很管用——把PWM信号接到LED上串好限流电阻。如果LED在闪说明频率太低如果LED稳定发光、亮度随占空比变化说明频率已经过了人眼敏感区。用这招粗筛频率再借示波器精调整个调试节奏会快很多。
返回列表