不知道你是不是也有这样的经历:手边一堆5V电源、USB充电头,想驱动一个12V的电脑散热风扇,结果接上之后扇叶纹丝不动。或者你早就听说过“电感升压电路”,但一直没搞清楚PWM占空比和输出电压到底是什么关系。这篇文章就是从一个非常具体的小风扇DIY项目出发,把PWM控制电感升压电路这件事从头到尾讲明白,包括boost升压原理、器件选型、STM32CubeMX配置、现场调试和避坑经验。内容偏实操,适合正在学STM32、或者有一定电子基础但想动手做开关电源类小项目的朋友,纯硬件玩家也可以看,里面同样给了NE555的模拟PWM方案,不用敲一行代码就能跑起来。
1. 先搞懂:PWM凭什么能把电压“升”上去
1.1 电感升压的本质是电感的“电流惯性”
很多人第一次看到boost升压电路会觉得反直觉:一个电感、一个MOS管、一个二极管、一个电容,怎么就把5V变成12V了?关键就藏在电感的特性里:电感中的电流不能突变,它会在你断开开关的瞬间拼命维持原来方向的电流。
整个电源变换的过程可以拆成三步:
- MOS管导通:输入电压Vin通过电感和导通的MOS管直接到地,电感两端加上正向电压,电流线性上升,电感内部储存磁场能量。
- MOS管关断:电感为了维持原来的电流方向,会产生一个反向电动势,这就是我们常说的“反压”。这个电压不会小,它等于Vin叠加电感上的感应电动势,足以把电流压过二极管,给输出电容和负载供电。
- 下一个周期重复:PWM每来一个周期,电感就完成一次“储能—释放”的循环,输出电容负责平滑电压,最终负载上看到的就是稳定的直流高压。
用一个生活化类比:电感就像水锤效应里的管道,你突然关掉阀门,水不会立刻停下来,反而会继续往前冲,形成一股高压冲击。PWM就是那个反复开关阀门的控制器,每关一次,就把水“泵”高一点。
1.2 PWM占空比怎么决定输出电压
boost电路在连续导通模式下,理想输出电压和占空比D的关系非常简单:
Vout = Vin / (1 - D)
如果输入5V,想让输出12V,理论上需要的占空比是:
D = 1 - Vin / Vout = 1 - 5/12 ≈ 0.583
也就是PWM高电平时间占整个周期的58.3%左右。但这个公式是理想情况,真实电路里有二极管压降、电感直流电阻、MOS管导通损耗,实际需要的占空比会略高一点。如果肖特基二极管压降算0.4V,那么D会更接近0.6。
我把几个常用目标电压列在下面,方便你心里有个数。注意这只是理论估算,实际空载和带载会不一样。
| 输入电压 | 目标输出电压 | 理论占空比D |
|---|---|---|
| 5V | 9V | 0.444 |
| 5V | 12V | 0.583 |
| 5V | 15V | 0.667 |
| 12V | 24V | 0.500 |
1.3 PWM频率不是随便选的
很多人第一次写PWM程序,直接把频率设成1kHz甚至50Hz,然后发现电感吱吱叫、输出电压纹波大得离谱。开关电源的PWM频率直接影响电感电流纹波,计算公式是:
ΔI = Vin × D / (f × L)
以5V输入、D=0.6、电感100uH为例,如果频率是25kHz,那么电感电流纹波大约是:
ΔI = 5 × 0.6 / (25000 × 0.0001) = 1.2A
这个纹波太大了,如果负载只有0.2A,电感电流会直接断续,输出特性会很差。把频率提高到100kHz,同样条件下纹波降到0.3A,就合理很多。所以实际DIY我一般建议把开关频率放在50kHz到100kHz之间,好处有两个:一是电感可以选小一点,二是避开人耳最敏感的20kHz到20kHz音频范围,不容易啸叫。
还要特别提醒一句,舵机PWM那种“周期20ms、脉宽1到2ms”的信号是控制信号,不是功率开关信号,千万不要套到升压电路里,不然MOS管会一直处于半开半关状态,发热量非常吓人。
1.4 STM32定时器PWM输出模式和四线风扇PWM调速的区别
STM32F103的定时器PWM输出模式里,ARR决定了PWM周期,CCR决定了占空比,频率公式是:
f = 定时器时钟 / ((PSC + 1) × (ARR + 1))
这个后面会详细算。但这里先强调一个大坑:市面上常见的四线电脑风扇,风扇本体的PWM调速信号通常是25kHz的方波,但那个信号不是直接串在风扇电源线上斩波的,而是给风扇内部的驱动芯片一个调速指令,由芯片控制电机换相和功率管。我们这篇文章做的是外部功率变换,用PWM控制升压电路给风扇供电,如果你把风扇自己的PWM调速线直接拿去驱动MOS管,很容易出问题。这两者的用途千万别搞混。
2. 器件选型:哪些东西能直接买到,哪些要避坑
2.1 核心器件清单
下面是一份我实际做这个项目时用的物料清单,全部都是常见器件,电子市场或者各种开源硬件平台都能买到。
| 器件 | 型号/参数 | 说明 |
|---|---|---|
| MOS管 | AO3400 或 IRLZ44N | 必须是逻辑电平MOS,Vgs阈值低 |
| 电感 | 100uH~220uH,额定电流≥2A | 用功率电感,别用色环电感 |
| 肖特基二极管 | SS34 / SS54 | 耐压40V左右,正向压降低 |
| 输出电容 | 470uF/25V电解 + 10uF陶瓷 | 电解滤低频,陶瓷滤高频 |
| 输入电容 | 100uF/16V | 稳定输入电压,降低电源波动 |
| 栅极电阻 | 10Ω~22Ω | 限制栅极充放电速度,减少振铃 |
| 下拉电阻 | 10kΩ | 防止上电瞬间MOS管误导通 |
| 负载 | 12V直流无刷风扇 | 参考电流0.1A~0.3A |
如果你手头有IRF540、IRF640这类经典MOS管,我建议先放一边。这些管子Vgs阈值高,3.3V或5V的PWM高电平根本不能把它们彻底打开,管子会工作在放大区,通态电阻巨大,发热严重。选AO3400就是因为它Vgs(th)只有0.65V到1.45V,3.3V逻辑电平就能可靠驱动。注意同型号SOT-23小封装散热能力有限,如果电流超过1A,尽量选更大封装的逻辑电平MOS。
2.2 3.3V单片机为什么推不动普通MOS管
这个问题在热词里反复出现:PWM接MOS管发热。一个很常见的原因是大家以为“PWM高电平”就等于“MOS管完全导通”,实际上普通增强型MOS管要完全导通,Vgs通常需要10V左右。STM32F103的GPIO输出高电平只有3.3V,勉强超过阈值,但管子只是打开了很小一部分,导通电阻可能有几百毫欧甚至几欧,流过大电流时损耗全变成热量。
解决思路有三条,按优先级排:
- 换逻辑电平MOS。这是最简单的方案,AO3400、IRLZ44N、IRLR2905都行。
- 增加栅极驱动电路。用两个三极管搭推挽驱动,或者直接用栅极驱动芯片,把3.3V PWM转换成10V到12V的栅极驱动信号。
- 做电平转换。如果信号路径较长或者要求高精度电平转换,可以用专门的PWM电平转换电路,但对这个DIY项目来说属于杀鸡用牛刀。
我的建议是刚开始玩先选逻辑电平MOS,等后面做更大功率项目再研究驱动芯片。栅极驱动问题不解决,换再好的电感电容,升压电路也很难稳定工作。
2.3 电感饱和是一个常被忽略的坑
电感选型时,大家往往只关心电感量,忽略了额定电流和饱和电流。电感一旦饱和,感值会急剧下降,电感电流变成“一根导线”直接烧穿MOS管。一般情况下,电感额定电流至少要大于负载电流的两倍,峰值电流要按“负载电流 + 一半的纹波电流”估算。
举个例子,风扇负载0.2A,输入5V,理想情况下输入平均电流大约是12×0.2/5≈0.48A,但考虑效率折算,实际输入电流可能在0.6A左右,而开关管和电感上的峰值电流可能超过1A。所以我做这个项目直接选了220uH、2A额定电流的功率电感,低频纹波小,又有足够裕量,不会因为过流而饱和。
3. 两套PWM生成方案,按你的条件选
3.1 纯硬件方案:NE555产生PWM,不用写代码
如果你不想碰单片机,NE555是最快上手的办法。用NE555搭无稳态多谐振荡器,输出一个固定频率的方波,就可以当作PWM信号送给MOS管栅极。
想要独立调节占空比,需要在充放电回路上各加一个二极管,让充电和放电走不同路径,这样充电电阻和放电电阻可以分别调节。基础频率公式是:
f ≈ 1.44 / ((R1 + 2R2) × C)
高电平时间约等于:
tH ≈ 0.693 × (R1 + R2) × C
低电平时间约等于:
tL ≈ 0.693 × R2 × C
举个例子,R1取1kΩ,R2用20kΩ电位器,C取1nF,中心频率大约35kHz,占空比随电位器调节可以从很小做到很大。实测时注意频率会随着占空比微调而变化,但对风扇这种负载而言并不敏感,完全可以接受。
这个方案最大的优点是调试方便,拨动电位器就能看到风扇转速变化,特别适合第一轮原理验证。缺点是没有闭环,输出受输入电压和负载影响大,后面如果想做稳定控制,还是要上单片机。
3.2 STM32F103定时器PWM输出:最推荐的灵活方案
用STM32做主控,最大的好处是频率和占空比都能精确控制,而且可以方便地增加反馈和保护逻辑。下面以STM32F103在CubeMX里配置TIM2_CH1输出25kHz PWM为例,走一遍完整流程。
在CubeMX里的配置步骤:
- 选择芯片型号STM32F103C8T6,RCC打开HSE外部晶振。
- 时钟树确认定时器时钟是72MHz。STM32F103的TIM2挂载在APB1上,APB1本身可能是36MHz,但定时器时钟会自动倍频到72MHz,这个细节很多人容易看错。
- 左边选择TIM2,Channel1模式设为PWM Generation CH1。
- 配置参数:Prescaler设为71,Counter Period设为39。这样PWM频率就是:
f = 72MHz / ((71+1) × (39+1)) = 72MHz / 2880 = 25kHz
- 初始Pulse设为0,这样刚上电时不会突然给风扇全速。
- 生成工程代码后,在main.c里启动PWM输出。
HAL库代码其实非常简洁:
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); void set_duty(uint8_t duty) // duty 0~100 { uint32_t pulse = (uint32_t)duty * (htim2.Init.Period + 1) / 100; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse); }注意STM32的PWM占空比计算公式是CCR / (ARR + 1),不是CCR / ARR,因为计数器是从0开始计数的。我这里设置的ARR寄存器值是39,实际周期是40个计数节拍,所以100%占空比需要Pulse设为40,而不是39。
开机的软启动也很重要,不要直接set_duty(60),会让输出电容和风扇瞬间承受冲击,也容易诱发过压。我习惯用一个循环慢慢爬坡:
for (uint16_t i = 0; i <= 30; i++) { set_duty(i * 100 / 30); HAL_Delay(20); }这样从0到100%平滑过渡,实测输出稳定很多。
如果你做的是多路输出或者更复杂的波形,可以用PWM加DMA直接批量更新比较寄存器,让CPU在波形发送期间完全休息。CubeMX里可以勾选DMA请求,代码里使用HAL_TIM_PWM_Start_DMA,原理就是让DMA在更新事件触发时自动把脉冲值搬到CCR寄存器里。
3.3 其他常见控制方式:输入捕获、IR2104和仿真验证
再补充几种热词里经常出现的方向,方便你后面扩展。
- 输入捕获测外部PWM信号:比如外部给你一个可调PWM信号,你想把它当成调速给定,就可以用另一个定时器的输入捕获通道,比如“PWM input on CH1”,捕获周期和高电平时间,然后映射成自己的PWM占空比。
- 半桥驱动芯片:如果以后用IR2104这类芯片驱动半桥或H桥电路,本质思路也一样,重点是处理好上管的自举电容和死区时间。单相H桥PWM整流器就是用这种思路把交流侧功率可控的,底层思想和boost纯粹程度不一样,但PWM开关的概念是相通的。
- Simulink辅助设计:先搭一个boost模型跑仿真,确认环路参数和拓扑工作点,再把代码移植到STM32,适合项目复杂度上来以后用。
4. 小风扇DIY案例:从面包板搭起来到转速可调
4.1 接线顺序与检查细节
下面的接线表以STM32PWM输出为例,NE555方案只是把“PWM_IN”换成555的输出,其余部分完全相同。
| 连接点 | 从哪来 | 到哪去 |
|---|---|---|
| 输入电源Vin | 5V/2A适配器正极 | 电感一端、输入电容正极 |
| GND | 电源负极 | STM32/555的GND、MOS管源极、输入电容负极 |
| L | 电感另一端 | MOS管漏极、肖特基二极管阳极、开关节点 |
| D | 肖特基二极管阴极 | 输出电容正极、风扇正极 |
| MOS栅极 | PWM输出经过10Ω电阻 | 到MOS栅极,同时在栅极和源极之间加10k下拉 |
| 风扇 | 输出正极/负极 | 风扇红线接正极,黑线接负极 |
接线顺序建议:
- 先焊或插好输入电容、MOS、电感、二极管、输出电容,这些是功率回路,走线尽量短。
- 再接入PWM信号和下拉电阻,确认栅极不会悬空。
- 输出端先接万用表或者假负载,不要直接上风扇。
- 上电前检查二极管方向,阴极必须朝向输出,反了会短路;电解电容极性也必须确认,反接会冒烟甚至爆开。
我以前为了省事用面包板搭过这个电路,发现高频开关电源在面包板上问题非常多:跳线过长产生寄生电感,接触电阻不稳定,输出电压一抖一抖的。后来改成洞洞板焊接,问题立刻少了大半。你如果只想快速验证原理,面包板可以用,但建议跳线越短越好;想稳定带风扇,直接上洞洞板。
4.2 上电调试与波形观察记录
上电调试我习惯分三步走。
第一步,先不给MOS管PWM信号,测量输出端电压。D=0时,MOS管完全关断,但输入会通过电感和二极管直接到输出,所以输出电压约等于输入电压减去一个二极管压降,大约4.6V左右,这是正常现象,不是故障。
第二步,给一个很小的固定占空比,比如20%,用万用表测输出电压。如果接线没问题,输出会升到6V到7V左右。这时候可以用示波器看MOS管栅极波形,确认PWM的幅值和边沿是否干净。没有示波器也没关系,可以临时在输出端并一个电阻和电容做RC滤波,用万用表量电压平均值,也能观察到占空比变化带来的电压变化。
第三步,带上风扇负载。占空比从20%开始逐步增加,记录输出电压和电流,每次加5%左右,观察风扇是否平稳加速。
下面是一份我在5V输入、220uH电感、25kHz PWM条件下实测的记录,不同器件参数会有差异,但趋势是一致的。
| 占空比D | 输出电压 | 输出电流 | 现象 |
|---|---|---|---|
| 0% | 4.6V | 0A | 风扇不转 |
| 20% | 6.3V | 约0.02A | 风扇轻微抖动,不转 |
| 30% | 7.8V | 约0.05A | 风扇开始缓慢转动 |
| 40% | 9.2V | 约0.09A | 风扇明显转动 |
| 58% | 11.9V | 约0.18A | 风扇接近额定转速 |
| 70% | 14.2V | 约0.25A | 风扇高速,偏危险 |
看到70%占空比输出冲到14V,就知道开环系统必须限制最大占空比。如果程序跑飞或者上位机误发一个100%占空比,输出可能会冲到20V以上,风扇会“飞车”,电容也可能过压。所以我在程序里给set_duty函数加了一个上限,防止占空比超过70%,并且在输出端并了一个15V稳压管,做硬性钳位保护。
4.3 PWM调速与风扇的实际匹配
用升压PWM同时调电压来调速,有一个问题:风扇启动时需要的电压比维持转动高不少。从表格也能看到,20%占空比时虽然已经有6.3V输出,但风扇只是轻微抖动,因为电压不足以克服静摩擦和轴承阻力。实际使用中我建议把最低占空比设得稍微高一点,比如30%起步,让风扇能稳定转动,然后在这个基础上调速。
另外,风扇本身是有最低启动电压的,如果你把占空比调到很低,风扇可能不转但一直处于堵转状态,反而会烧电机。所以不只是“转速越低越好”,要留一个合理的工作范围。
还有一种更精细的做法是:先用这个升压拓扑把输出电压稳定在12V左右,再单独用一路低端MOS开关或者四线风扇的PWM引脚去调速,这样电压不随风扇负载变化。本文的DIY案例属于最简单的“调压即调速”方案,够用,但你要清楚它的局限性,后面需要更稳定输出时就要加闭环了。
5. 常见问题与排查技巧实录
5.1 问题速查表
我把这个项目里能遇到的高频问题整理成了一张表,排查时按顺序过一遍会快很多。
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| MOS管发热严重 | 栅极驱动不足、频率太高、电感饱和、占空比过大 | 用逻辑电平MOS;降低频率或改用低栅电荷MOS;换大电流电感;限制最大占空比 |
| 电感啸叫 | PWM频率落在音频范围、电感磁芯松动、纹波过大 | 提升频率到50kHz以上;换更大电感量;固定电感线圈 |
| 输出电压比预期低 | 输入电压不足、二极管压降大、电感内阻大、MOS导通电阻大 | 提高输入电源电流能力;换肖特基二极管;换低内阻电感;适当提高占空比 |
| 空载电压过高 | boost开环电路输出轻载时电压会上升 | 接假负载或加电压反馈闭环 |
| 带载后电压猛掉 | 电感饱和、输入电源限流、输出电容不够 | 换大饱和电流电感;换大功率电源;加大输出电容 |
| 风扇不转或转速异常 | 启动电压不足、占空比太低、风扇正负极接反 | 提高最低占空比;检查风扇供电线颜色 |
| 输出超压导致风扇飞车 | 占空比失控、程序跑飞、反馈失效 | 加稳压管钳位、限制最大占空比、软启动 |
5.2 PWM接MOS管发热的深度剖析
这是热词里被反复问到的问题,值得单独拿出来说。MOS管发热来源有三个:
- 导通损耗,P=I²×Rds(on)。栅极驱动电压不足时,Rds(on)会大幅上升,发热迅速。
- 开关损耗,P≈0.5×Vin×I×(tr+tF)×f。栅极电阻太大、驱动芯片驱动能力弱,会导致开关边沿变慢,开关损耗急剧增加。
- 体二极管反向恢复损耗,在boost拓扑里主要是二极管的恢复时间,所以要用肖特基而不是普通整流管。
排查的时候先看栅极波形。如果上升沿和下降沿都很缓,那重点查栅极驱动链路的驱动能力和栅极电阻阻值。如果波形很陡但还是发热,那重点查电感和二极管损耗。
我个人的经验是:栅极电阻不是越大越好,也不是越小越好。太大开关变慢,太小容易产生振铃和EMI。对于AO3400这种小管子,10Ω左右通常比较合适;对于大电流MOS,可以结合推挽驱动把栅极电阻降到几欧。
5.3 我踩过的坑与实际教训
第一个坑:用色环电感做升压。色环电感是小型固定电感,额定电流通常只有几十毫安到几百毫安,用于这个场景很容易饱和,一接负载输出电压就狂掉,我还以为是占空比算错了。后来换成220uH/2A的功率电感,问题立刻消失。
第二个坑:用IRF640直接接STM32。脉宽没变,但MOS管热到烫手,输出电压很低。用万用表一量栅极电压只有3.3V,而IRF640的Vgs(th)典型值2V到4V,根本没完全导通。换了AO3400以后,发热问题基本消失,在0.2A负载下MOS管只是微温。
第三个坑:冷启动直接给定大占空比。有一次我在调试软件时把初始占空比从0改到80%,一上电风扇像发疯一样高速转动,输出电容吱的一声,吓出一身汗。后来我给所有PWM输出统一加上软启动和限幅,上电从0开始每20ms加1%,稳得不能再稳。
6. 更进一步:闭环控制和故障保护怎么加
6.1 电压闭环:让输出电压真正“可设定”
开环方案虽然能做出来,但当输入电压波动或负载变化时,输出电压会跟着跑,风扇转速忽高忽低。一个很自然的升级就是加电压闭环:
- 用STM32的ADC采集输出电压,可以通过分压电阻把12V降到3.3V以内。
- 在代码里把实际电压和目标电压做差,用简单的PI调节器计算新的占空比。
- 限制占空比范围和每次调节步进,防止环路振荡。
ADC采样不需要很快,1kHz左右就足够,但要注意开关噪声会叠加在电压信号上,建议取多个样本做移动平均,或者在ADC引脚前加一个RC低通滤波,截止频率放在几百赫兹。
PI参数不需要特别精确,先试P再试I。P太大容易震荡,I太大会有超调,这个具体数值和电感、电容、负载都有关,多调几次就有手感了。
6.2 PWM故障保护和拓展应用
热词里出现的“PWM故障保护”在工业驱动里非常重要,STM32F103的定时器本身支持刹车功能,可以通过BKIN引脚紧急关断PWM输出。在DIY项目里,你可以用一个比较器监测输出电流,超过阈值后触发紧急关断,或者直接把BKIN引脚接到一个硬件过压保护信号上。
另外一个很实用的方向是温控风扇。热词里提到“STM32控制温度传感器DS18B20读温度输出PWM”,其实就是把本文的PWM占空比和温度值关联起来。DS18B20用单总线协议读回温度,然后把温度映射到占空比:
- 温度低于40°C,占空比设为0,风扇停转。
- 温度在40°C到70°C之间,占空比线性从20%升到80%。
- 温度高于70°C,占空比封顶在90%,避免风扇超压。
关键点是温度采样和PWM更新不要在同一个阻塞式延时循环里做,建议用定时器中断做时间基准,主循环只做状态管理,这样风扇转速控制才平滑。
6.3 多路PWM、DMA和仿真建模的扩展思路
最后聊几个非常容易做上瘾的扩展方向。如果你觉得单路PWM不够,可以用定时器的多个通道输出多路不同占空比的PWM,配合DMA可以让CPU完全解放出来,适合做呼吸灯、多路风扇组或者动画效果。如果可以接受电脑端建模,推荐先在Simulink里把boost拓扑和PI控制器跑一遍,观察启动冲击和负载突变下的响应,心里有数以后再写STM32代码,会少走很多弯路。如果之后涉及到H桥或者电机控制,核心思想同样是“用一个高频开关信号控制功率管的导通时间”,理解了电感升压,再去理解其他开关变换器会轻松很多。
这次DIY案例我前前后后做了三版:第一版用面包板和NE555,验证原理;第二版换STM32和洞洞板,解决散热和稳定性;第三版加了电压闭环和过压保护,才真正敢拿它去驱动风扇长时间运行。如果你也准备动手,我建议按这个节奏来,不要一上来就追求最高效率或者最强保护,先让电路“跑起来”,再逐步加东西。等你亲自测过栅极波形、听过电感啸叫、摸过MOS管温度,很多之前觉得模糊的概念,比如占空比、开关频率、电感饱和,都会变成非常直接的体感记忆。