
前阵子帮入门朋友整理了一套基于STM32F103C8T6的三相SPWM逆变器Demo从MATLAB/Simulink仿真到PCB设计再到固件源码把整条链路走通之后发现一个很多人都会纠结的问题C8T6这颗72MHz主频、64KB Flash的小芯片到底能不能扛起三相逆变器的活答案是不仅能扛而且能扛得很从容。用来做实验级逆变器、电机驱动、变频电源这颗芯片的资源完全够用加上国产替代型号基本引脚兼容性价比也说得过去。这篇文章就跟大家把整条链路捋一遍从SPWM的底层原理、关键参数计算到STM32定时器和DMA生成六路PWM再到Simulink仿真和PCB布局布线的实操细节一次讲透。1. 三相SPWM逆变器的核心逻辑先搞懂调制原理再动手1.1 三相桥式逆变电路到底在干什么所谓逆变本质上是把直流母线电压通过开关管的规律通断变成频率和幅值都可控的交流电。三相逆变器的主电路是三相全桥一共6个MOSFET分布在三个桥臂上每个桥臂上下两管串联上下管互补导通。三个桥臂的中间点就是三相输出端。以母线电压Vdc为例某个开关周期内某相的下管导通、上管关断该相输出近似0V上管导通、下管关断该相输出近似Vdc。这里有个关键认知三相逆变器输出的原始波形是PWM方波不是正弦波正弦波是后续由电机绕组电感或者LC滤波器平滑出来的。PWM波的开关频率和基波频率是两个完全不同的概念很多人第一次调试时对着示波器上一堆方波发懵就是没想清楚这一点。同一桥臂的上下两管是绝对不允许同时导通的一旦直通母线直接被短路MOSFET瞬间烧毁。所以在上下管切换之间必须插入一段死区时间这段看似简单的延迟恰恰是新手最容易翻车的地方。1.2 SPWM调制为什么对称规则采样法适合单片机SPWM的中文全称是正弦脉宽调制核心思想是让开关管导通的占空比不再恒定而是按正弦规律变化。最直观的实现方式是把正弦参考波和一个高频三角载波进行比较正弦值大于载波时输出高电平否则输出低电平。这样每个开关周期内脉冲宽度正比于正弦参考值的瞬时大小输出基波就是正弦波形。这里有个工程实现上的选择问题。自然采样法需要求正弦波与三角波斜边的真实交点在单片机里要解方程计算量很大而且放在中断服务程序里会增加不少负担。工程上更常用的是对称规则采样法在一个载波周期内把正弦参考值当作恒定值用近似交点代替真实交点。这个方法在72MHz主频的STM32F103C8T6上跑计算量完全可以接受。三相一共只需要计算3个通道的比较值更新一次定时器比较寄存器剩下的交给硬件外设去产生PWM。1.3 三个核心参数载波频率、死区时间、调制比在设计之前建议先把三个参数定下来不然程序写到一半再改非常痛苦。载波频率fc也就是PWM开关频率。选得太低电流纹波大滤波电感和电容的体积跟着变大电机负载时还可能听到明显的啸叫选得太高MOSFET的开关损耗上升驱动芯片压力也大。实验级逆变器典型选12kHz到20kHz我常用的值是16kHz兼顾损耗和滤波效果。死区时间td取决于MOSFET的关断延迟和驱动芯片的响应时间。普通低压MOSFET比如IRF540N关断时间也就几十纳秒加上驱动芯片的传输延迟死区时间1us到2us就够用。但如果用IGBT关断时间明显更长死区得放到2us到5us。死区时间过短会导致直通烧管子过长会增加输出电压的畸变。调制比M定义为正弦参考波幅值与三角载波幅值之比。在三相两电平逆变器中输出相电压基波幅值约等于M乘以Vdc的一半。比如母线电压100V想让输出相电压基波峰值40VM大约就是0.8。调制比最大理论值是1超过1就进入过调制区输出波形会出现明显畸变一般不建议。1.4 两电平逆变器与三电平逆变器的区别很多人在查资料时会看到三电平NPC拓扑好奇为什么不直接上三电平。这里简单对比一下。对比项两电平逆变器三电平NPC逆变器每相输出电平数2个±Vdc/23个Vdc/2、0、-Vdc/2输出谐波谐波相对较大谐波含量低THD更优开关管电压应力需承受母线电压钳位二极管分担应力降低控制复杂度简单一路PWM即可需要中性点电位的平衡控制适用场景低压实验、中小功率电机驱动中高压大功率变频、储能变流器STM32F103C8T6的TIM1高级定时器天然支持两电平互补PWM和硬件死区做三电平需要额外处理钳位逻辑和时序分配资源会比较紧张不适合作为入门起步方案。2. 硬件链路怎么搭从功率器件到STM32引脚分配2.1 MOS管还是IGBT先看电压和功率等级功率开关管选型直接影响整个系统的成本和调试难度。低压应用首选MOSFET高压大功率场景才需要考虑IGBT。用F103C8T6做的实验级逆变器母线电压一般不会超过100V功率从几十瓦到几百瓦这个区间正好是低压MOSFET的舒适区。低压MOSFET的优点很明显导通电阻低、开关速度快、栅极电荷小用IR2103这类半桥驱动芯片就能很好驱动。常用型号比如IRF540N100V/33A、IRFB4110100V/120A后者适合功率更大的版本。选型逻辑建议这样走先定下母线电压和最大负载电流然后留出1.5到2倍的电压余量和电流余量。比如母线48V、计划输出10A那MOSFET至少选100V/20A以上的管子。2.2 驱动电路与自举电容上管驱动没那么神秘STM32的引脚输出3.3V电平直接驱动不了MOSFET的栅极高压侧的MOSFET源极电位还是浮动的所以必须用半桥驱动芯片。IR2103S是经典选择国产替代比如EG2133、EG2134也很常见引脚大多兼容。驱动芯片内部集成了电平位移电路配合自举电容就能驱动上管。自举电容的选型有个粗略估算方法根据上管栅极电荷Qg和最大导通时间Ton_max来计算Cboot要大于Qg乘以Ton_max再除以允许的电压跌落。实际操作中典型值直接取10uF并一颗0.1uF瓷片电容就够用10uF负责维持上管导通时的栅极电荷0.1uF负责滤除高频噪声。需要注意自举电容的容量对最低开关频率有要求频率太低时下管导通时间不够自举电容充不满上管就会驱动不足这也是SPWM载波频率不能取得太低的原因之一。另外在驱动芯片输出到MOSFET栅极之间要串一个栅极电阻典型10欧到22欧。这个电阻用来限制栅极充放电电流、抑制振铃。阻值太小栅极波形振荡严重阻值太大开关损耗上升占空比失真。新手建议先用10欧用示波器看栅极波形再微调。2.3 STM32F103C8T6最小系统与引脚分配F103C8T6是LQFP48封装资源不算宽裕但合理分配完全够用。做三相逆变器时最关键的是TIM1高级定时器的输出引脚布局如下功能引脚说明TIM1_CH1PA8A相上管PWMTIM1_CH1NPB13A相下管PWMTIM1_CH2PA9B相上管PWMTIM1_CH2NPB14B相下管PWMTIM1_CH3PA10C相上管PWMTIM1_CH3NPB15C相下管PWM剩下还能用的引脚分配一个UART串口用于调试一个ADC通道采样母线电压或电流一个GPIO按键用于启停控制。最小系统的要点我踩过不少坑列一下关键点8MHz无源晶振配两颗20pF负载电容走线尽量短复位电路用10k上拉电阻加0.1uF电容BOOT0直接接地BOOT1悬空保证从Flash启动SWD调试接口占用PA13和PA14这是烧录调试的生命线板子设计时一定要预留。供电方面3.3V靠近每个VDD引脚放100nF退耦电容这个细节不能省。特别提醒一下VDDA引脚给ADC采样供电的最好串一个磁珠或小电感隔离数字噪声不然母线电压采样会飘到你怀疑人生。关于国产替代GD32F303系列、MM32F103等型号引脚基本兼容F103C8T6程序在标准外设库或HAL库下通常小改就能跑这在当前供应链环境下是个重要优势。3. 固件实现定时器加DMA生成六路SPWM3.1 为什么必须用TIM1高级定时器F103C8T6的定时器资源里TIM2、TIM3、TIM4只能输出普通PWM没有互补通道也没有硬件死区。三相逆变器需要六路PWM每路都要求上下管互补并带死区只有TIM1和TIM8这两个高级定时器能做到。TIM1的CH1、CH2、CH3各自有一路互补输出CH1N、CH2N、CH3N正好对应三相六管。更关键的是TIM1的刹车功能和死区生成是硬件逻辑不占用CPU干预。在BDTR寄存器里设定死区时间后硬件会自动在互补PWM切换时插入死区这个可靠性远高于软件延迟翻转引脚。3.2 正弦表与比较值计算最稳的查表法生成SPWM最简单直接的方式是查正弦表。我习惯用一个周期256点的表用int16_t数组存正弦值避免浮点运算。进阶玩法是用720甚至1024点波形更细腻但C8T6的Flash空间够用这点完全不是瓶颈。相位累加的思路是这样设定一个载波频率比如16kHz定时器ARR设置为450072MHz主频除以16kHz减1。在定时器更新中断里每进一次就按频率步进更新三相相位索引// 伪代码示意 phase_index (phase_index step) 0xFF; sin_a sin_table[phase_index]; sin_b sin_table[(phase_index 85) 0xFF]; // 120度对应约85个点 sin_c sin_table[(phase_index 171) 0xFF]; // 240度对应约171个点 ccr_a half_arr (int16_t)(half_arr * M * sin_a 15);120度的相位差在256点表中就是85个索引点240度就是171个点。这里有个细节相位的偏移量建议用正数绕一圈的方式不要用负索引和运算时也方便。比较值CCR的范围要控制在0到ARR之间否则输出会饱和。用这种软件更新CCR的方式CPU在16kHz开关频率下大概每62.5us中断一次在72MHz主频下计算量可以轻松承担。如果后续还要跑FOC或者并网控制算法可以把正弦表更新交给DMA搬运。原理是定时器更新事件触发DMA把内存中预计算好的CCR数组搬到TIM1的CCR寄存器里全程不需要CPU干预。不过要处理好DMA的环形缓冲和主循环的同步不然更新时机不对会出现毛刺这个属于进阶优化建议先把中断方式跑通再考虑。3.3 死区时间配置与刹车保护死区时间在TIM1_BDTR寄存器中配置。标准外设库下示例TIM_BDTRInitStructure.TIM_OSSRState TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState TIM_OSSIState_Disable; TIM_BDTRInitStructure.TIM_LOCKLevel TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime 72; // 72MHz时钟对应约1us计算公式是这样72MHz时钟周期约13.9nsDTG字段低7位直接表示死区时间等于DTG乘以Tdts。DTG72时死区时间约为72乘以13.9ns约等于1us。不同DTG分段模式下计算方式略有差异但实验板上用这个简单公式足够。刹车保护是TIM1的另一大优势。把过流比较器的输出信号接到TIM1的BKIN引脚配置刹车有效极性后一旦触发PWM输出会立即进入安全状态同时产生刹车中断。这个响应过程完全由硬件逻辑完成不依赖中断服务程序和软件堆栈的响应时间可靠性碾压软件关PWM。3.4 频率调节与软启动V/F曲线和防冲击三相逆变器驱动电机时通常需要V/F控制基频以下恒压频比保证电机的磁通恒定基频以上恒压避免过压。实现方式就是在正弦表相位累加的步进上做文章。基波频率f决定了步进值step等于f乘以表点数除以载波频率。50Hz基波、16kHz载波、256点表step大约是0.8实际用定点数累加取整后作为索引。启动瞬间的电流冲击也要考虑。直接把调制比M从目标值一步拉到位电感电流会瞬间冲得很高严重时直接过流保护。我习惯做一个软件软启动上电后M从0开始每个载波周期增加0.001大概0.8秒内逐渐升到目标值。这个方法成本极低但对MOSFET安全工作有明显帮助。4. MATLAB仿真先行Simulink里把逻辑跑通再动手画板4.1 Simulink模型搭建Universal Bridge和PWM Generator在MATLAB/Simulink里建三相逆变器仿真用Simscape Electrical库里的Universal Bridge模块最方便。把桥臂数设成3开关类型默认理想或者是MOSFET模型直流源设置成母线电压输出接一个Three-Phase Series RLC Load参数按实际负载设定。PWM脉冲生成可以有两种思路一种直接用PWM Generator模块输入调制波信号另一种更接近真实硬件实现的方式是自己搭一个三角载波比较电路用三个正弦波信号和一个高频三角波比较比较结果同时经过一个带死区的切换逻辑模块直接送进Universal Bridge的6个门极信号。这个做法的好处是仿真结构更贴近STM32上实际运行的逻辑后面写固件时可以直接把仿真里的正弦表相位关系搬过去。仿真步长建议和载波周期匹配。载波16kHz仿真最大步长取1e-6s别为了跑得快把步长设得太大否则开关边沿的细节全丢了。4.2 从相电压到线电压波形分析和THD仿真跑50ms输出稳定后打开Scope看波形。A相相电压对直流母线中点来看应该是幅值正负Vdc/2的SPWM方波串但基波频率是50Hz的正弦轮廓。再看线电压Uab用相减得到的波形应该是幅值在Vdc、0、-Vdc之间跳变的台阶波形这是因为线电压等于两相相电压之差。用Powergui工具里的FFT Analysis选择分析窗口可以看到相电压和线电压的谐波分布。理想两电平SPWM的低次谐波幅值较低谐波能量集中在开关频率及其边带附近这是正常现象。如果仿真中看到明显的低次谐波比如3、5、7次谐波很大通常要回头检查三相正弦参考波是否严格相差120度以及有没有过调制。4.3 仿真参数怎么对应到硬件电路仿真最大的价值是用理想模型验证逻辑然后反哺实际参数。以输出滤波电感为例如果带的是纯电阻负载需要加LC滤波器。滤波电感的取值可以根据电感电流纹波要求来算。假设额定电流10A纹波取0.3倍即3A母线72V占空比约0.8开关频率16kHz那么L约等于(72V乘以0.8)除以(16kHz乘以3A)大概1.2mH。这个电感量比电机绕组电感大不少所以离网带阻性负载或者接市电并网时滤波器设计要谨慎。仿真参数建议这样设置一组Vdc100V、fc10kHz、M0.8、f50Hz、负载每相10欧姆加5mH电感。跑完之后记录相电压的基波幅值和THD再用同样的参数在硬件上复现对排查问题非常有帮助。另外多说一句MATLAB版本只要能装Simulink和Simscape Electrical功能差异不大关键是仿真模型参数要和目标硬件对应清楚。5. PCB设计布局、布线、铜皮挖空与DRC一个都不能少5.1 功能分区和电流环路功率区和控制区必须分开三相逆变器PCB上最核心的布局原则是让主回路的大电流开关环路面积足够小。这个环路是母线电容到上管上管到下管下管再回到母线电容。环路面积越大寄生电感越大开关瞬间就会和MOSFET的结电容产生LC振荡产生电压尖峰轻则影响EMC重则直接击穿MOSFET。所以布局的第一步是把母线电容紧贴MOSFET桥臂让电流路径形成一个尽量紧凑的回路。控制部分比如STM32、晶振、SWD调试接口放在板子的另一端。中间是驱动芯片和隔离带。控制地和大电流的功率地之间建议用0欧电阻或者磁珠单点连接避免功率地的大电流噪声串进控制地导致采样信号和PWM波形出现莫名毛刺。我做第一版板子时图省事把驱动芯片放得离MOSFET比较远结果栅极驱动波形振铃严重后来把驱动芯片挪到离mos管栅极尽量近的位置问题就消失了。栅极驱动线路尽量短这条经验比什么降噪技巧都直接。5.2 走线宽度、间距与铜皮挖空大电流走线的宽度可以按经验公式估算1oz铜厚下1mm线宽大约能过1A到2A电流具体还受走线长度和散热条件影响。三相输出线和母线走线建议至少2mm宽能铺铜的地方就直接铺铜必要时加开窗补焊锡增加载流能力。之前有人问到AD20中PCB板铜皮挖空怎么操作以及有什么作用这里展开说一下。铜皮挖空在不同场景下用途不同在控制区和功率区之间画一条开槽Keepout相当于物理隔断切断地平面上的噪声传播路径在MOSFET大焊盘下方或散热过孔区域挖空可以避免大面积敷铜产生不必要的涡流和局部过热高压和低压区域之间通过开槽拉开爬电距离这对安规测试非常关键。PCB层数的选择上实验板用双面板完全没问题但如果是长期运行或者要过EMC测试的版本建议直接上四层板顶层走信号内层1做地平面内层2走电源或功率地底层走大电流。四层板的地平面连续性优势在逆变器这种大电流开关场景下非常明显。5.3 DRC检查不等于画完板子在AD20或嘉立创EDA中画完PCB后DRC检查必须认真跑一遍。至少检查这几项安全间距Clearance不能小于0.2mm短路和未连接网络过孔和焊盘的连接方式泪滴是否补全。逆变器板子上高压区和低压区的间距问题DRC的规则设置里要单独设规则不然默认间距也许满足不了实际工作的爬电要求。说句实在话DRC只是底线检查并不保证板子功能正确。真正要仔细核对的是每个MOSFET的栅极走线长度是否尽量一致采样信号走线有没有经过功率噪声区域晶振底下的地平面有没有被切断。这些靠DRC查不出来只能靠布局时的经验积累。6. 硬件调试与故障排查烧了几片管子之后的经验总结6.1 上电前必做的安全检查清单每次新板子到手我都会先做一遍固定流程检查这习惯帮我避免了不少损失万用表蜂鸣档量母线正负极之间是否短路上桥臂MOSFET的D和S之间是否短路先只给控制板供3.3V不接功率母线用示波器看六路PWM波形是否正常确认上下管互补、死区时间正确用示波器双通道同时测量同一桥臂的上下管栅极波形观察互补切换瞬间有没有交叠导通的风险给低压12V母线空载上电测量三相输出端的相电压波形确认SPWM的频率和调制比正常逐步升高母线电压到目标值同时观察母线电流和输出波形。这个流程能挡住90%的新手问题。千万别一上来直接上高压大功率那等于拿MOSFET做实验。6.2 烧MOSFET的排查链路烧MOSFET是逆变器调试中最常见也最让人头疼的问题。烧管子之后先去测三个关键位置栅极驱动波形有没有异常振铃死区时间是否真的生效了母线电压开关尖峰有没有超过MOSFET的Vds额定值。我在实际项目中遇到过一次诡异的情况静态看PWM波形完全正常一加母线电压就烧下管。排查到最后发现是上电瞬间单片机还没初始化完成某些IO口处于不确定状态驱动芯片输出导致桥臂直通。解决办法是在单片机和驱动芯片之间加上下拉电阻确保PWM信号在单片机复位期间处于确定电平同时把BOOT0的上拉和复位电路设计成上电默认安全状态。另一个高频翻车点是示波器测量时的地线问题。普通探头的地线夹如果直接夹在220V母线相关节点轻则测量噪声巨大重则短路损坏设备。在逆变器这种开关电源系统中强烈建议用差分探头或者隔离通道实在没有就测低压控制侧的波形不要去碰高压节点。6.3 实测波形和经验技巧调试时实测三相输出我习惯先看线电压波形。线电压的台阶状态能够直观反映上下管开关逻辑是否正确。正常情况下的线电压应该在母线电压和零电平之间切换如果看到某个相缺失一整个导通周期大概率是正弦表相位错位。还有个小技巧用万用表的交流电压档去快速判断三相是否都有输出比搬示波器快得多。虽然万用表读的是RMS值但能快速排除单相无输出的低级问题。家用储能方向的朋友如果要做类似逆变器测试阶段务必注意安全输入母线串一个限流电阻或者灯泡万一有故障还能缓冲一下比直接炸管要温柔得多。6.4 个人的一点体会现在回想起来这种低压实验板最锻炼人的地方反而不是把原理图画得多漂亮而是把MATLAB里的理想模型一步步变成能在桌面上跑起来的真板子。我自己前前后后烧掉了差不多七八片MOSFET基本都集中在死区时间没设对和母线电容布局太远这两类问题上。后来养成了一个习惯每次改版先整理一张“参数—现象”的对应表记录载波频率、死区时间、母线电压和实际波形的关系调试时不靠玄学效率高很多。后续如果大家感兴趣我计划再写一篇把CLARK和PARK变换之后的三相闭环控制整理出来那个就是真正往FOC和并网方向进阶了。