简介:面向嵌入式开发与电力电子入门人群,这份基于STM32微控制器的逆变器设计资料,完整覆盖了从原理分析、硬件搭建到软件实现的关键链路。项目以正弦波逆变器为核心,首先讲解直流转交流的基本原理,以及IGBT、MOSFET等功率开关器件的通断控制,再借助脉宽调制技术、定时器输出与模数转换反馈闭环,实现输出电压和频率的精确调节,帮助读者建立电源类项目的完整设计思路。压缩包共十个文件,大小约十七点九二兆字节(17.92MB)。文件类型包括三份设计文档、三个工程压缩包(内含原理图、PCB制板文件、控制软件与正弦波生成工具)、两个网页说明页面以及两份电路图文件,可以按照“文档说明—源码例程—电路设计”三层结构对照学习。同时,设计中涉及的过流、过压、欠压保护思路也有助提升系统可靠性。目前已有两千四百一十九人学习下载。内容直指定时器生成脉宽调制信号、模数转换采样、比例积分微分控制及正弦波调制算法,并配套可打样验证的电路工程,适合正在筹备电源类课程设计、毕业设计或希望动手实践逆变器项目的开发者参考。
1. 让逆变器真正跑起来,最难的不是功率管,而是那条反馈回路
基于STM32的逆变器设计,听起来是把SPWM和功率管搭在一起就能出正弦波,实际上我见过太多样机卡在同一个地方:开环能亮灯,闭环就翻车。真正决定一个逆变器能不能带上负载、能不能稳住电压的,是一整条从电压电流采样、数字PID到占空比更新的闭环链路。STM32在这条链路里承担的任务很明确:根据母线电压和输出反馈,实时算出下一拍该输出多宽的脉冲,而功率管、驱动、滤波电路只负责把脉冲还原成交流。这篇笔记适合正在做单相离网逆变器、UPS或车载电源的开发者,也适合想从“点亮LED”进入功率电子门槛的初学者。全文按拓扑选型、硬件设计、SPWM生成、双闭环调试、白盒验证的顺序推进,把能直接搬走的参数和踩过的坑都写在后面。
2. 主电路拓扑与器件选型:单相全桥为什么是首选方案
2.1 从半桥到全桥:耐压、电流与纹波的权衡
单相逆变器常见有两种桥式方案:半桥和全桥。半桥的母线电压利用率只有一半,要输出220V有效值,直流母线得做到约700V以上,这对电容耐压和功率管耐压都是不小的压力。全桥用四个管子把母线直接切换到负载,母线利用率高一倍,同样输出220V时母线可以降到约350V,管子耐压余量更从容。所以在200V以上输出的单相逆变器里,全桥几乎是默认选择。
全桥的另一个好处是等效开关频率翻倍。两对桥臂互补工作,输出端等效纹波频率是单个桥臂的两倍,LC滤波器的尺寸可以明显缩小。代价是驱动路数翻倍、直通风险更大,需要更严格的管理。这些代价在软件层面可控,而半桥在高压侧的器件成本和可靠性问题更难接受。
我一般会这样选型:500W以下、低压输入的便携设备,可以考虑半桥;其余情况优先全桥。母线电压越低,全桥优势越明显。整体结构也不复杂:直流母线、全桥、LC低通滤波、负载,STM32只接管桥臂控制信号。
2.2 关键器件参数:滤波电感、电容与功率管耐压的匹配原则
滤波环节决定输出波形质量。常见做法是先定开关频率,再照截止频率反推L和C。假设开关频率定在20kHz,LC低通截止频率取开关频率的1/10左右,也就是2kHz。输出功率1kW、输出电压220V时,等效负载约48Ω,按截止频率公式可以算出L约2.5mH、C约2.2μF;实际为了兼顾电感体积和阻尼,L会取小一些并配合阻尼电阻。
功率管耐压按母线最高电压加30%~50%余量留。母线350V时选650V管比较稳妥,别卡着额定值用。同功率下,IGBT耐压高、饱和压降大、开关速度慢,适合10kHz上下但不追求高频的场合;MOS管开关快、无拖尾电流,适合20kHz以上。做1kW以下高频PWM逆变器,我倾向于用MOS管,驱动简单,损耗模型也比较清楚。
电感还要留意饱和。峰值电流和纹波电流叠加后,磁感应强度不能进饱和区,否则电感量骤降,输出电流尖刺跟着变大。选型时至少留20%电流裕量,优先选低损耗的铁硅铝或非晶磁环,普通工频铁芯在高频下损耗会高到烫手。
2.3 死区时间该怎么设?不能只靠“1μs够用”
死区是同一桥臂上下管都关断的一小段间隔。设短了直通烧管,设长了输出电压波形出现平顶,THD上升。设多少不是拍脑袋,它和功率管关断延迟、驱动芯片传输延迟、栅极电阻拖慢的关断速度都有关系。常见做法是查器件手册里的关断延迟和下降时间,两者相加后再加20%~30%余量。对大部分MOS管加栅极驱动芯片的组合,0.5~2μs覆盖了绝大多数场景。
死区还有一个容易被忽略的影响:带电流方向不同,死区期间输出被钳到不同的电平,等效于在调制波里注入低次谐波。负载越重,影响越明显。所以仅仅用PI去压输出电压误差,压下来的多是基波,谐波还在。要求不高时靠“死区取小+输出滤波”压过去;要求高时再做死区补偿。
死区补偿的原理不神秘:根据当前电感电流方向,在占空比上等效加减一个死区时间对应的脉宽。电流采样不是每个周期都有?那就用估算的电流方向做补偿,效果也能接受。这个话题放到后面闭环调参时再展开。
3. 从原理图到量产板的硬件设计:驱动、采样、保护三个必守环节
3.1 驱动电路:隔离、自举与栅极电阻怎么选
全桥四路驱动需要隔离。常见做法是用自举驱动的半桥驱动芯片,每个芯片负责一对桥臂,自举电容在低端管导通时充电,给高端管浮地供电。自举电容容量不能太小,否则高端管开通瞬间压降过大;也不能太大,否则充电时间不够。1μF~10μF是常用区间,再并一个0.1μF陶瓷电容吸收高频纹波。
栅极电阻决定开关速度。阻值小,开关损耗低,但关断瞬间的电压尖峰和EMI更严重;阻值大,EMI好转,但开关损耗上升,死区时间也要跟着放宽。10Ω到22Ω是我常用的起点,再按驱动波形振铃微调。开通和关断可以分开走不同阻值:关断路径并联二极管加小电阻,既压住尖峰又不明显拖慢关断。
驱动芯片的供电电压也值得盯住。大部分驱动芯片推荐12V~15V,电压低了管子欠驱动,导通压降变大、发热严重;电压过高甚至打坏栅极。调试时先量驱动芯片的Vcc是否稳定,很多奇怪的“功率管发热”其实是驱动电源没起来。
驱动信号和单片机之间还要处理地噪声。STM32的地和功率地最好单点连接,驱动芯片输入侧走线要短而粗,必要时串一个小电阻抑制振铃。别小看这一步,它比换驱动芯片更能解决莫名其妙的误触发。
3.2 电压与电流采样:高共模电压下的三种方案选择
输出交流电压是浮动的,直接用电阻分压到单片机引脚不行,共模电压会把ADC口打坏。常见做法有三种:电阻分压加差分放大器、隔离运放、电压互感器。差分放大器成本低、带宽高,适合控制和保护共用一路信号;隔离运放安全性好,但价格高,适合对地环路敏感的高压场合。做单相离网逆变器,差分放大器方案性价比最高。
电流采样同样要处理参考地。低压侧用采样电阻加差分放大,成本最低;高压侧或需要隔离时用电流互感器或霍尔传感器。电流互感器不能测直流,但逆变器输出是交流,正好匹配,而且互感器次级可以接成电流型,抗干扰能力更强。
采样点位置直接影响控制效果。常见做法是电流采样放在LC滤波前,采的是电感电流——它包含负载电流和电容电流,适合做电流内环保护;放在滤波后采负载电流,更贴近用户侧需求,但相位会受负载影响。我习惯把硬件采样留两路,一路给内环,一路留作保护监控。
采样时序也要同步到PWM上。电感电流在PWM开关瞬间有尖刺,如果错误时刻触发ADC,采到的是开关噪声而非真实电流平均值。常见解法是把ADC触发和定时器更新事件对齐,在PWM周期中心采样,那段窗口里电流纹波基本对称,平均值误差最小。
3.3 保护电路:母线过压、过流、过热三件套怎么接到STM32
软件保护再快也要走中断和比较,而功率管在微秒级就可能损坏,所以过流保护应该独立在硬件里完成。常见做法是电流采样信号经过比较器,超过阈值立刻封锁PWM输出——STM32高级定时器的刹车输入端正是干这个的。刹车信号可以来自比较器输出,再通过锁存电路保持故障状态,由软件复位解除。
母线过压用电阻分压后比较器监测。母线电压超过设定值时,既可以触发刹车,也可以软件进入降压或卸载流程。最关键的是母线电容耐压要按最高可能电压加至少20%余量,否则保护还没动作电容先炸。
过热保护相对宽松,用NTC贴在散热器上,温度阈值根据管子结温估算来定。这里有一个工程细节:结温不是外壳温度,要按热阻估算温差。散热器60℃不代表结温只有70℃,大电流工况下差个三五十度很正常。
4. 生成SPWM的三种典型路径:定时器、DMA、高级定时器死区
4.1 对称规则采样:正弦表怎么生成
数字SPWM最常见的实现是规则采样。把正弦波在一个周期里离散成N个点,每个点对应一个PWM占空比,定时器按载波频率不停地更新比较寄存器,输出脉宽就跟着正弦规律变化。这里的N等于载波频率除以调制波频率。20kHz开关频率、50Hz调制波时,每个正弦周期有400个PWM周期,也就是400个采样点。
规则采样里,对称规则采样在三角载波顶点采样,能稍微提高等效精度,而且便于在PWM中心时刻触发ADC采样,正是控制算法需要的时间基准。正弦表也不是一定要在单片机里算,离线算好放进常量数组更省事,改调制比时把整个表乘一个系数即可。下面这个Python脚本可以直接生成一个400点的正弦表:
import math N = 3600 # 定时器自动重载值,决定PWM周期计数 M = 400 # 载波比:20kHz载波 / 50Hz调制波 table = [] for i in range(M): phase = 2 * math.pi * i / M duty = 0.5 + 0.45 * math.sin(phase) # 调制比0.9,留出死区余量 table.append(int(duty * (N - 2))) print(', '.join(str(x) for x in table))这里的调制比取0.9,是为了给死区和母线波动留出占空比余量。输出表里每一项对应一个PWM周期里CCR应写入的值,查表时从0递增到399再回绕,正弦波就能连续输出。
4.2 用定时器更新中断更新比较值:最小可用方案
最简单的方式是让高级定时器工作在中央对齐模式,更新中断每次到来,就把正弦表里下一个值写进比较寄存器。下面这段基于HAL库的初始化配置展示了如何把TIM1设置成20kHz载波:
// 基于HAL库的TIM1初始化,输出两路互补PWM TIM_HandleTypeDef htim1 = {0}; htim1.Instance = TIM1; htim1.Init.Prescaler = 0; // 72MHz直接计数 htim1.Init.Period = 3600 - 1; // 3600个计数=20kHz载波 htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim1);这段代码把TIM1配置成中央对齐模式:ARR=3599,预分频为0,所以计数周期恰好是72MHz/3600=20kHz。中央对齐模式下更新事件发生在计数值等于0和ARR的瞬间,正好对应三角载波的波峰和波谷。CH1与CH1N的占空比由CCR1控制,两者天然互补,只需在BDTR里设置死区。更新中断里的逻辑也很直接:
// 假设正弦表table[400],idx是查表索引 uint16_t ccr = table[idx++]; if (idx >= MODULATION_POINTS) idx = 0; __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, ccr);注意别在中断里做浮点运算,查表已经足够。400点查表加一次寄存器写入,在72MHz主频下耗时不到几微秒,但中断仍是额外开销。如果整机还要处理键盘、显示和通信,载波频率再拉高时就开始挤压主循环带宽。
4.3 用DMA搬运正弦表:把CPU从中断里解放出来
更省心的做法是让DMA在更新事件里自动把正弦表数据搬到CCR寄存器,CPU完全不用管。正弦表存在内存里,DMA配置成循环模式,触发源选定时器的更新事件,传输方向从内存到外设,目标地址是TIM1的CCR1寄存器,数据宽度半字:
// 配置DMA通道,循环搬运正弦表到TIM1->CCR1 hdma_tim1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tim1_ch1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tim1_ch1.Init.MemInc = DMA_MINC_ENABLE; hdma_tim1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_tim1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_tim1_ch1.Init.Mode = DMA_CIRCULAR;重点在循环模式和半字宽度上:循环模式保证400个点搬完后又从头开始,正弦波才能连续;半字宽度是因为CCR寄存器是16位。MemInc打开表示源地址按数组递增,PeriphInc关闭表示目标地址只在CCR一个位置反复写。带宽足够时,DMA方案基本零中断负载。注意,更新事件是每个PWM周期来一次,400点表意味着每400次更新才走完一个正弦周期,这正好和载波比对应。
4.4 高级定时器死区:BDTR寄存器与自动刹车
STM32F1系列里只有TIM1和TIM8带互补输出和死区插入,这是硬件做逆变器的基础。互补输出使能后,CH1N自动跟随CH1取反,二者之间的死区由BDTR寄存器里的DTG字段控制。用HAL库配置时,只需填一个死区计数值:
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; sBreakDeadTimeConfig.DeadTime = 72; // 约1μs,实际按定时器时钟换算 sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; sBreakDeadTimeConfig.BreakFilter = 0; HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);注意DeadTime不是纳秒数,而是DTG字段值。当前定时器时钟是72MHz,每个计数周期约13.9ns,DTG=72对应约1μs。这个值要和选型阶段算出来的“关断延迟+下降时间+余量”核对。BreakState打开后,刹车输入一旦有效,硬件立刻封锁PWM输出,这正是上一章说的硬件过流保护通道。如果只用普通定时器,虽然也能输出PWM,但补不出互补通道和死区,只能靠软件翻转IO去模拟,在功率应用里风险太大。
5. 电压电流双闭环怎么调:常见问题与排查
5.1 双闭环的控制结构:为什么电流内环必须比电压外环快
逆变器输出侧可以抽象成一个由LC组成的二阶对象。如果不加内环,直接用电压误差去驱动SPWM,电感电流会成为外界的干扰通道:负载一拉大,输出电容电压立刻被拉低,电压环要等电流建立起来才能修正,动态响应慢得明显。把电感电流放进内环后,负载变化先表现为电流改变,内环一个周期内就能把电流调整回来,电压外环只需要校平静态误差。
常见控制周期是:电流环10kHz~20kHz,电压环5kHz~10kHz,两者都在PWM更新中断里完成。数字控制比模拟多了一拍延时:采样在当前周期,输出要到下个周期才生效。这一拍在高开关频率下会引入相位滞后,所以比例增益不能往死里加,否则会出现高频振荡。
5.2 整定步骤:先内环后外环,用阶跃响应看趋势
我的调试顺序一直是固定的:先去电流环,再去电压环。先把电压环断开,只跑电流内环,给定一个阶跃电流指令,看电感电流跟踪速度和超调。先给一个较小的比例系数,慢慢往上加,同时观察波形是否出现“一个周期两三个振荡”的毛刺感。出现毛刺就调低比例,再加一点点积分项消除静差。
电流环调好后,把输出接上阻性负载,再把电压环接入。电压环的比例同样从小往大调,看输出电压从阶跃到稳定的过程。理想的响应是电压建立迅速、超调小于10%、没有持续振荡。注意每次改动只调一个参数,别同时改比例和积分,否则出了问题不知道是哪个引入的。
5.3 常见问题一:空载波形好,一带载输出电压就跌
现象:空载时示波器看到干净的正弦波,挂上几百瓦负载后,输出电压明显跌落,波形顶部或底部出现削平。原因:电压环带宽太低,负载电流突变时,外环来不及把占空比补上去;也可能是电感饱和,峰值电流时电感量掉下来,导致输出电流波形畸变。解决:先看电感电流波形是否在负载加重时出现明显非线性;再确认电压环的积分增益是否足以让稳态占空比跟上负载。逐步加大电压环积分系数,可以考虑加入负载电流前馈。
5.4 常见问题二:已经设了死区,上电还是炸管
现象:样机上电瞬间电流飙到几十安,功率管炸开,或者桥臂上下管同时导通形成直通。原因:死区设了,但只在正常工作时有效;上电瞬间定时器还没初始化完成,PWM输出处于不确定状态,或者刹车信号没生效。解决:把PWM输出初始化放在最后一步,先让刹车有效、输出关闭,再启动定时器;同时检查驱动芯片输入端的上拉或下拉电阻,别让空闲状态下电平悬空。还有一个隐蔽点:死区时间按常温设好,高温下器件延迟变大,要按最差工况留余量。
5.5 常见问题三:闭环跑起来后波形叠加高频毛刺
现象:空载开环时波形很干净,闭合环路后,正弦波上出现振铃样毛刺,频率通常在几千赫兹到几十千赫兹不等。原因:电流环比例增益过大,把LC谐振频率附近的噪声放大;或者ADC采样时刻正好落在PWM开关尖峰上,反馈信号本身带了高频分量,数字滤波器又没把它滤掉。解决:先把电流环增益调回去,确认毛刺消失;再把ADC触发点移到PWM周期中心,给采样信号加同带宽的RC低通;如果仍然振荡,还要检查控制周期与PWM中心对齐的方式,避免形成相位滞后超过180°的正反馈。
5.6 常见问题四:STM32频繁复位,程序像中了邪
现象:逆变器带载运行时,单片机时而重启,有时伴随ADC读数跳变。原因:功率地与信号地走线不当,地弹噪声灌进了复位引脚;或者驱动芯片的供电不稳,在桥臂切换瞬间拉低Vcc。解决:先确认复位引脚波形没有毛刺,必要时加RC或专用复位监控;再把功率地和信号地单点连接,采样和驱动的布局靠近单片机一侧;最后查驱动芯片电源是否足够大,自举电容容量是否偏小。这种事排查起来没有捷径,把每一级电源波形都录下来看,通常能找到真凶。
6. 白盒验证与进阶改造:把样机调到稳定安全的最后一公里
样机不是“能输出正弦波”就算完。我习惯固定做四步白盒检查:第一步,在额定负载下看驱动波形,确认高低端栅极波形没有振铃、死区时间与设定一致;第二步,用电子负载从空载到满载逐级加,记录输出电压有效值、THD和整机效率;第三步,把负载从满载突卸到空载,看输出电压过冲是否超过安全范围,这一步能暴露环路稳定性问题;第四步,故意制造一次过流,确认硬件刹车能在几个微秒内封锁PWM。四步全过,我才会把板子交给下一步。
进阶改造可以从三条线走。一是电压波形前馈:把母线电压实时纳入占空比计算,抵消母线纹波对输出的影响,这对母线电容偏小的方案特别有用。二是加锁相环和过零检测,让输出频率和相位可跟随外部基准,为并网或双机并联留出接口。三是把控制方式从查表SPWM升级为闭环SPWM加谐波补偿,在电流环里叠加几个低次谐波的反向分量,能明显降低非线性负载下的THD。
我最想强调的习惯是:每改一个参数,都把当时的示波器截图和触发条件存下来,标注好开关频率、负载大小和控制周期。这套做法帮我在很多次“改完反而更差”的循环里快速回退,也避免同事接手时把参数调得乱七八糟。希望这些经验和踩坑记录能帮到你,至少让你在第一次给逆变器上电时,能少炸几块板子。
本文还有配套的精品资源,点击获取