基于STM32的单相交流电子负载:SPWM生成与电流闭环设计
1. 从电赛A题说起单相交流电子负载到底是个什么东西如果你参加过电子设计竞赛或者正在准备某个电力电子方向的毕业设计大概率听过“单相交流电子负载”这个题目。我第一次接触它是在帮学弟看电赛A题的方案当时他拿着一堆MOS管和电感问我“这玩意儿到底怎么把电能‘吃’进去又‘吐’出来”这个问题其实问到了核心——电子负载不是把能量变成热耗散掉而是要把被测电源输出的交流电能“回收”利用或者至少做到可控地模拟各种负载特性。传统负载就是电阻、电感、电容接上去之后功率因数固定、电流波形固定想测一个电源在不同负载条件下的表现你得换一堆电阻箱又笨又热。电子负载用电力电子变换器来模拟负载你可以通过程序设定它呈现阻性、感性、容性甚至模拟一个非线性负载电流波形想怎么捏就怎么捏。单相交流电子负载就是针对单相交流电源的测试设备输入侧接被测电源输出侧通常接电网或者直流母线把能量回馈回去。那SPWM在这里扮演什么角色简单说SPWM就是“用开关管拼出一个正弦波”的技术。你有一堆直流电压想让输出端得到一个正弦交流电压或者电流最直接的办法就是让开关管按照正弦规律通断输出一系列宽度按正弦变化的脉冲再经过电感电容滤波就得到了正弦波。这个“按正弦规律改变脉冲宽度”的过程就是SPWM。在单相交流电子负载里SPWM用来控制输入侧变换器的电流让输入电流跟踪给定参考从而实现功率因数可控、电流波形可控。STM32在这套系统里就是大脑。它要完成几件事采集输入电压电流、计算参考电流、生成SPWM驱动信号、处理保护逻辑、跟上位机通信。为什么选STM32而不是其他MCU因为STM32的定时器资源丰富高级定时器带互补输出和死区插入正好驱动全桥电路ADC采样速度快配合DMA可以做到无CPU干预的连续采样主频够高跑一个电流环加SPWM生成绰绰有余。我见过有人用DSP做性能确实好但成本和开发门槛对电赛或者本科毕设来说偏高STM32是性价比最平衡的选择。这套东西适合谁看如果你正在做电赛电源类题目、电力电子课程设计、或者想入门数字电源控制这篇文章就是给你写的。我会从整体方案讲起把SPWM生成的原理、STM32的配置、电路参数计算、调试中踩过的坑全部摊开讲。不需要你有很深的电力电子背景但至少得知道MOS管怎么开关、电感电容的基本特性。2. 整体方案设计与核心思路拆解2.1 为什么选全桥SPWM电流闭环这套架构单相交流电子负载的拓扑选择其实有好几种Boost型、Buck型、全桥型、半桥型。Boost型只能升压输入电压低于母线电压时没法工作Buck型只能降压输入电压高于母线时受限。全桥结构最灵活四个开关管组成H桥通过SPWM控制可以实现输入电流的双向流动既能吸收能量也能回馈能量而且输入电压范围宽母线电压只要高于输入电压峰值就能正常工作。我最终选的是电压型全桥PWM整流器拓扑输入侧接电感输出侧接直流母线电容。这个结构的好处是输入电流连续、功率因数可调、能量可以双向流动。具体来说输入电感的作用是储能和滤波让电流纹波控制在合理范围直流母线电容稳定母线电压给开关管提供稳定的直流源四个MOS管组成两个桥臂每个桥臂的上下管互补导通通过SPWM调制让桥臂中点输出一个高频脉冲序列其基波分量跟踪输入电压。为什么不用半桥半桥结构少两个管子但输入电流只能单向流动没法实现能量回馈而且直流母线电压利用率低。全桥虽然多两个管子和驱动电路但换来的性能提升完全值得。在电赛这种需要展示“能量回馈”功能的场合全桥是标配。2.2 SPWM调制策略的选择单极性还是双极性SPWM调制方式直接决定了输出波形质量和开关损耗。双极性SPWM是同一个桥臂的上下管互补导通输出在两个电平之间切换谐波含量大但实现简单。单极性SPWM是每个桥臂独立控制输出在三个电平之间切换谐波含量小但控制逻辑复杂一些。我选的是单极性倍频SPWM。具体做法是左桥臂用正弦波和三角波比较生成驱动信号右桥臂用反相的正弦波和同一个三角波比较生成驱动信号。这样输出端的等效开关频率是载波频率的两倍谐波集中在两倍载波频率附近滤波器设计更容易。实测下来同样20kHz载波频率单极性倍频的输出电流纹波比双极性小一半左右。这里有个细节要注意单极性调制时两个桥臂的驱动信号必须严格同步否则会出现桥臂直通。STM32的高级定时器可以生成互补带死区的PWM但两个桥臂之间还需要相位关系正确。我的做法是用一个定时器生成两路比较值分别控制两个桥臂通过更新比较值来实现正弦调制。2.3 STM32的选型与资源分配我用的STM32F103C8T6也就是常说的“蓝板子”。有人会问F103主频才72MHz够用吗实测下来跑一个20kHz的电流环加SPWM生成CPU占用率不到30%。关键是资源分配要合理。定时器方面TIM1是高级定时器带互补输出和死区插入用来生成四路PWM驱动全桥。TIM2用来做系统时基和任务调度。TIM3用来捕获输入电压的过零信号做同步。ADC用规则通道扫描模式配合DMA搬运采样输入电压、输入电流、母线电压三个量。DMA通道要配置好不然ADC数据会覆盖。GPIO分配要提前规划PWM输出占用PA8、PA9、PA10、PA11这是TIM1的通道1到4。ADC输入用PA0到PA2。串口用PA9和PA10但注意PA9和PA10和TIM1的通道2、3冲突所以要么用重映射要么换串口。我最后用的是USART2PA2和PA3避开冲突。2.4 关键参数计算电感、电容、开关频率怎么定输入电感的值决定了电流纹波大小。电感越大纹波越小但体积和成本上去了动态响应也变慢。计算公式是L (Vin_peak × D) / (ΔI × fsw)。Vin_peak是输入电压峰值D是占空比ΔI是允许的电流纹波fsw是开关频率。假设输入电压有效值24V峰值就是34V。开关频率20kHz允许纹波为额定电流的20%额定电流5A那ΔI就是1A。最恶劣工况是占空比0.5的时候代入公式L (34 × 0.5) / (1 × 20000) 850μH。实际取1mH留点余量。直流母线电容的选择要看母线电压纹波要求。母线电压纹波主要来自输入电流的二次谐波分量。计算公式是C Iin_peak / (2 × ω × ΔVbus)。Iin_peak是输入电流峰值ω是电网角频率ΔVbus是允许的母线电压纹波。假设输入电流峰值7A电网频率50Hz允许纹波5V那C 7 / (2 × 314 × 5) 2229μF。实际取2200μF再并一个薄膜电容滤高频。开关频率的选择要权衡频率高电感和电容可以小但开关损耗大驱动电路要求高频率低损耗小但滤波器体积大。20kHz是个甜点刚好在音频范围之上不会产生可听噪声开关损耗也可以接受。3. SPWM生成与STM32定时器配置的硬核细节3.1 SPWM的本质用面积等效原理拼出正弦波SPWM的核心思想是“面积等效”——把正弦波分成N等份每一份的面积用一个等幅不等宽的矩形脉冲来等效。脉冲的宽度按正弦规律变化中心位置对齐。这样得到的脉冲序列经过低通滤波后基波就是原来的正弦波。具体实现时用一条正弦调制波和一条高频三角载波比较正弦波大于三角波时输出高电平小于时输出低电平。三角波的频率就是开关频率正弦波的频率就是输出基波频率。调制比M 正弦波幅值 / 三角波幅值决定了输出基波幅值。M最大为1此时输出基波幅值为母线电压的一半单极性或母线电压双极性。这里有个常见误区很多人以为SPWM的直流电压利用率只有86.6%其实那是SPWM在线性调制区的情况。86.6%的来源是SPWM线性调制时输出相电压基波峰值最大为Vdc/2而方波逆变时相电压基波峰值为2Vdc/π两者比值为(π/4)/√3 ≈ 0.866。这个数字在选母线电压时很重要意味着如果你需要输出220V交流母线电压至少要220×√2/0.866 ≈ 359V。3.2 STM32定时器生成SPWM的三种方法第一种是查表法。提前算好一个正弦周期的PWM比较值存在数组里定时器更新中断里依次读取数组更新比较寄存器。优点是计算量小缺点是频率分辨率受表长限制变频时需要重新算表。第二种是实时计算法。在定时器中断里用sin函数实时计算比较值。优点是频率任意可调缺点是sin计算耗时F103没有浮点单元用查表加插值更实际。第三种是DMA搬运法。把正弦表存在内存里配置DMA在定时器更新事件时自动把比较值搬到CCR寄存器。CPU完全不参与可以腾出时间做其他事。我最后用的就是这种方法20kHz开关频率正弦表256点DMA循环搬运CPU占用率几乎为零。具体配置TIM1设置为中央对齐模式ARR设为系统时钟除以开关频率再除以2。比如72MHz主频20kHz开关频率ARR 72000000 / (2 × 20000) 1800。预分频器设为0。CCR1到CCR4分别对应四个通道。DMA配置为循环模式源地址是正弦表数组目标地址是TIM1-CCR1每次传输半字。注意DMA请求要选TIM1的更新事件。3.3 死区时间计算与设置死区时间是为了防止同一桥臂上下管直通。MOS管关断需要时间如果上管还没完全关断下管就开了母线直接短路管子瞬间炸掉。死区时间要大于开关管的关断时间加上驱动电路的延迟。我用的IRF540N关断时间约100ns驱动芯片IR2110的延迟约200ns所以死区时间至少设300ns。STM32的死区寄存器BDTR可以设置死区时间计算公式是DTG[7:0] × TdtgTdtg 1/72MHz ≈ 13.9ns。300ns / 13.9ns ≈ 22所以DTG设为22。实际我设了500ns留足余量。注意死区时间不是越大越好。死区太大会导致输出波形畸变因为死区期间输出电压由电流方向决定会产生额外的谐波。一般取开关管关断时间的2到3倍就够了。3.4 电流环设计PI参数怎么调电流环是让输入电流跟踪参考电流的关键。参考电流由输入电压乘以一个导纳值得到导纳值决定了输入阻抗也就决定了功率因数。如果导纳是纯实数输入电流和输入电压同相功率因数为1。PI调节器的参数整定是个经验活。我的做法是先只加比例环节慢慢增大Kp直到电流波形开始振荡然后取振荡临界值的60%作为最终Kp。然后加积分环节Ki从很小的值开始加观察稳态误差消除的速度直到响应速度满足要求又不超调。具体数值Kp 0.5Ki 0.01。这个值跟电感、采样周期都有关系换硬件就要重新调。有个技巧是把PI输出限幅在母线电压的90%防止过调制。4. 完整电路图解析与关键元器件选型4.1 主功率电路从输入到母线的每一个环节主功率电路分三部分输入滤波、全桥变换、母线电容。输入滤波是一个共模电感和一个X电容组成滤除开关频率的共模噪声。共模电感用锰锌铁氧体磁环双线并绕20匝电感量约1mH。X电容用0.47μF的薄膜电容耐压630V。全桥变换的四个MOS管用IRF540N耐压100V电流33A导通电阻44mΩ。为什么选它因为耐压够用母线电压最高60V电流余量大导通电阻小发热少。驱动芯片用IR2110自带自举电路可以驱动高压侧MOS管。自举电容用1μF的陶瓷电容自举二极管用UF4007。母线电容用两个2200μF/100V的电解电容并联再并一个10μF的薄膜电容。电解电容负责低频储能薄膜电容负责高频滤波。母线电容的耐压要高于母线电压的1.5倍100V耐压对应60V母线余量足够。4.2 采样电路电压电流怎么采才准输入电压采样用电阻分压。输入电压峰值34VADC参考电压3.3V分压比取1:12用1kΩ和11kΩ的电阻串联。分压后的电压经过一个电压跟随器缓冲再送到ADC。电压跟随器用LM358单电源供电注意输入共模范围要包含0V。输入电流采样用霍尔电流传感器型号ACS712-20A。它的输出是电压信号零点在2.5V灵敏度100mV/A。电流为正时输出大于2.5V为负时小于2.5V。这个信号直接送ADC但要注意ACS712的输出范围是0到5V而STM32的ADC参考是3.3V所以需要分压或者用运放调整。我的做法是用一个同相放大器把2.5V零点移到1.65V增益设为0.66这样±10A对应0到3.3V。母线电压采样也用电阻分压分压比1:20用1kΩ和19kΩ串联。同样经过电压跟随器送ADC。4.3 辅助电源从母线取电给控制电路供电控制电路需要3.3V和12V两路电源。3.3V给STM32和ADC12V给驱动芯片和运放。从母线60V降到12V用LM2596降压模块效率高发热小。再从12V降到5V用7805线性稳压给霍尔传感器和部分运放供电。最后从5V降到3.3V用AMS1117-3.3给STM32供电。这里有个坑LM2596的输入电压范围是4.5V到40V母线60V超了。所以要么用更高耐压的降压芯片要么从母线电容中间抽头取电。我的做法是用两个电容串联中间点作为30V再给LM2596供电。但要注意电容均压问题每个电容并一个均压电阻。4.4 驱动电路IR2110的自举原理与布线要点IR2110的高压侧驱动需要自举电容。原理是当低侧MOS管导通时自举电容通过自举二极管从12V电源充电当高侧MOS管需要导通时自举电容上的电压作为高侧驱动的电源。自举电容的容量要足够大保证在一个开关周期内电压下降不超过1V。计算公式是C ≥ Qg / ΔVQg是MOS管栅极电荷IRF540N的Qg约70nCΔV取1V所以C ≥ 70nF。实际取1μF余量充足。布线要点自举电容和自举二极管要尽量靠近IR2110的VB和VS引脚走线要短而粗。高侧和低侧的栅极驱动走线要分开避免耦合。功率地和信号地要单点连接防止开关噪声串入控制电路。5. 软件架构与核心代码实现5.1 主程序框架前后台中断软件架构采用前后台系统。后台是主循环处理串口通信、按键扫描、状态显示这些实时性要求不高的任务。前台是中断包括定时器更新中断、ADC采样完成中断、串口接收中断。主循环里做三件事一是每10ms更新一次参考电流的幅值根据设定的功率因数计算导纳二是每100ms更新一次OLED显示三是响应串口命令修改工作模式。定时器更新中断里做电流环计算。中断频率就是开关频率20kHz每次中断读取ADC最新值计算误差跑PI更新比较值。注意中断里不要做浮点运算全部用定点数。我把电流值放大100倍存成int16PI参数也放大100倍最后结果右移7位还原。5.2 ADC采样与DMA配置ADC配置为规则通道扫描模式扫描顺序是输入电压、输入电流、母线电压。触发源选定时器更新事件这样采样时刻和PWM同步避免采样到开关噪声。DMA配置为循环模式每次传输3个半字到数组。采样时刻很关键。如果采样时刻正好在开关管切换瞬间会采到尖峰噪声。我的做法是在定时器计数到ARR值的时候触发ADC这时候开关管已经稳定导通或关断噪声最小。STM32的ADC可以配置为在定时器上升沿触发配合中央对齐模式采样点正好在PWM周期的中点。5.3 电流环PI代码实现typedef struct { int16_t Kp; int16_t Ki; int32_t integral; int16_t out_max; int16_t out_min; } PI_Controller; int16_t PI_Update(PI_Controller *pi, int16_t error) { int32_t p_term (int32_t)pi-Kp * error; pi-integral (int32_t)pi-Ki * error; if (pi-integral pi-out_max) pi-integral pi-out_max; if (pi-integral pi-out_min) pi-integral pi-out_min; int32_t output p_term pi-integral; if (output pi-out_max) output pi-out_max; if (output pi-out_min) output pi-out_min; return (int16_t)output; }这段代码里Kp和Ki都是放大100倍的定点数。integral是积分累加器做了限幅防止积分饱和。输出也做了限幅防止过调制。实际运行时error是参考电流减去实际电流输出是调制波幅值。5.4 SPWM正弦表生成与DMA搬运正弦表用Excel或者Python生成256个点每个点是sin(2πi/256) × 1800 1800范围0到3600对应CCR值0到ARR。为什么加1800因为CCR值不能为负而且中央对齐模式下CCR值决定占空比1800对应50%占空比。DMA配置为循环模式源地址是正弦表数组目标地址是TIM1-CCR1传输长度256每次传输半字。DMA请求选TIM1的更新事件。这样每个PWM周期DMA自动把下一个正弦值搬到CCR1同时CCR2、CCR3、CCR4也需要更新但它们的值跟CCR1有相位关系。我的做法是用四个DMA通道分别搬运四路PWM的比较值正弦表有四个相位分别是0、π、π、0。6. 调试实录从炸管到稳定运行的踩坑记录6.1 第一次上电就炸管死区时间不够第一次上电我信心满满地给了24V输入结果一按启动按钮啪的一声两个MOS管炸了。用示波器看驱动波形发现上下管的驱动信号有重叠死区时间设了100ns但IR2110的传输延迟就有200ns实际死区是负的。教训死区时间必须大于驱动芯片延迟加上开关管关断时间。我后来把死区设到500ns再也没炸过。另外第一次上电一定要用低压比如12V并且串一个灯泡限流炸管也不会太惨。6.2 电流波形畸变采样时刻不对炸管修好后电流波形出来了但畸变严重过零点附近有明显的平顶。用示波器同时看PWM和电流发现电流在开关瞬间有尖峰而ADC正好采到了尖峰。解决调整ADC触发时刻从定时器更新事件改为定时器比较事件让采样点落在PWM周期中点。具体做法是把ADC触发源设为TIM1的CC4事件CC4的比较值设为ARR的一半。这样采样时刻正好在开关管稳定导通期间噪声最小。6.3 功率因数上不去参考电流相位偏差设定功率因数为1但实测只有0.85。用示波器看输入电压和输入电流的相位发现电流滞后电压约10度。原因是参考电流是由输入电压乘以导纳得到的但输入电压采样有延迟导致参考电流滞后。解决在参考电流计算里加一个相位超前补偿。具体做法是用一个二阶广义积分器SOGI生成输入电压的正交分量然后用正交分量和原分量合成超前相位。SOGI的代码不复杂两个积分器加交叉反馈带宽设为电网频率的2倍。6.4 母线电压泵升能量回馈没做好电子负载在吸收能量时母线电压会泵升。如果能量回馈回路没做好母线电压会一直升到电容炸掉。我的做法是在母线上并一个泄放电阻当母线电压超过设定值时用MOS管接通泄放电阻把多余能量消耗掉。泄放电阻用100Ω/50W的铝壳电阻MOS管用IRF540N。但泄放电阻只是权宜之计真正要做能量回馈需要在母线侧接一个并网逆变器把能量送回电网。这个复杂度就高了电赛阶段一般不做要求泄放电阻够用。6.5 常见问题速查表现象可能原因排查方法解决方法上电炸管死区不够、驱动故障示波器看驱动波形增大死区、检查驱动电流畸变采样时刻不对看采样点与PWM关系调整ADC触发时刻功率因数低参考电流相位偏差看电压电流相位差加相位补偿母线泵升能量回馈不足测母线电压加泄放电路波形振荡PI参数太激进减小Kp观察重新整定PI管子发热开关损耗大测管壳温度降低开关频率、加散热片7. 实测性能与优化方向7.1 实测波形与效率数据在24V输入、5A电流条件下实测输入电流THD约3.5%功率因数0.99效率约92%。效率损失主要来自开关损耗和电感铜损。开关损耗跟开关频率成正比如果把频率从20kHz降到10kHz效率能到95%但电感体积要翻倍。电流跟踪误差在稳态下小于2%动态响应时间约5ms。这个性能对于电赛和本科毕设来说完全够用。如果要进一步提升可以从几个方面入手一是用SiC或者GaN器件开关损耗大幅降低频率可以提到100kHz滤波器体积缩小二是用预测控制代替PI动态响应更快三是用锁相环精确同步电网相位功率因数可以做到0.999。7.2 从电赛到产品的差距电赛作品和工业产品之间还有很大距离。工业产品要考虑EMC、安规、热设计、可靠性、成本。比如EMC电赛作品一般不做传导辐射测试但产品必须过CE认证。热设计方面电赛作品加个风扇就行产品要做热仿真确保最恶劣工况下结温不超过限值。但电赛这套东西作为学习平台是极好的。你把SPWM、电流环、功率变换这些核心概念都摸了一遍再去看工业产品会发现底层原理是相通的。我在调试过程中最大的收获不是把电路调通了而是理解了“为什么采样时刻这么重要”“为什么死区不能太大”“为什么PI参数要折中”——这些经验在书本上是学不到的。7.3 后续扩展思路这套平台可以扩展成三相版本做三相交流电子负载用于测试三相电源。也可以加上并网功能把能量回馈到电网效率更高。还可以加上谐波发生功能模拟非线性负载测试电源的抗谐波能力。软件方面可以加上上位机界面用LabVIEW或者Qt做实时显示波形和参数。通信可以用串口或者CANCAN抗干扰能力更强适合工业现场。最后分享一个小技巧调试电流环的时候先用电阻负载代替被测电源这样输入电压是稳定的直流电流环更容易调。等电流环调好了再换成交流输入加上锁相环和相位补偿。这个顺序能帮你省下大量炸管的时间。