☰
STM32F103C8T6三相SPWM逆变电源实战:死区、LC滤波与PCB布局全解析
2026/10/28 18:04:55 网站建设 项目流程

简介:基于STM32F103C8T6单片机实现的三相SPWM逆变电源设计资料包,面向电力电子、嵌入式开发及硬件设计学习者,涵盖从原理图、PCB到软件源码的完整工程链。包内包含用Altium Designer打开的电路图与PCB文件、Keil5工程源码(含stm32f10x_tim.c等定时器与ADC配置)、PDF版电路图、元件清单Excel、硬件结构框图和程序流程图文档,以及参考论文和实物图,便于对照理解三相逆变桥驱动、SPWM波生成和采样反馈等关键环节。整个压缩包共385个文件,约30.42MB,主要文件类型包括C语言源码、头文件、Altium Designer工程文件(pcbdoc/schdoc)、PDF文档、Word说明及编译生成的hex、axf文件等,目录结构清晰,适合完整复盘或二次开发。目前已有4344人学习下载。资料从方案设计、硬件布局到软件调试均有覆盖,可直接用于毕业设计、课程项目或逆变电源产品预研,省去从零搭建工程和查阅芯片手册的耗时。

1. 为什么是STM32F103C8T6做三相SPWM逆变电源:这份资料解决什么问题

收到这份“基于STM32F103C8T6单片机设计的三相SPWM逆变电源AD原理图PCB+软件源码+文档资料.zip”,第一件事不是解压双击,而是先问一句:它到底帮你省掉了哪段路。这类项目的本质,是用一片64KB Flash、20KB RAM的Cortex-M3芯片,输出三组带死区的互补SPWM脉冲,驱动三相全桥逆变器,再经LC滤波得到三相正弦交流电。它覆盖了从AD原理图、PCB布局到Keil软件源码和说明文档的完整闭环,适合做UPS、电机驱动、实验室三相电源的入门原型。值不值得照抄,取决于你是否搞懂了背后的选型逻辑、死区时间、载波频率这几个要命参数。

2. 三相SPWM生成原理与定时器选型:查表法、引脚映射与死区参数

2.1 SPWM的两种生成方式:软件查表法与硬件PWM比较

SPWM的本质是“正弦波与三角载波比较”,输出脉宽按正弦规律变化的PWM脉冲。常见做法有两种:一种是在定时器中断里实时算正弦值并更新占空比,另一种是提前算好一张正弦表,中断里只做查表赋值。实时计算占用CPU太多,而且三角函数在Cortex-M3上跑起来开销不小;查表法用空间换时间,中断里只有三次数组读取和三次寄存器赋值,20kHz中断频率下对72MHz主频来说毫无压力。

查表法的另一个好处是波形可预期。载波20kHz、基波50Hz时,载波比正好是400,每个工频周期有400个PWM周期。把正弦表做成400点,每个PWM周期推进一点,基波频率精确等于50Hz。如果表点数和PWM周期数对不上,波形会引入次谐波,这是SPWM里最容易忽略的坑。下面用Python生成三相独立的400点CCR表,直接输出成C数组:

import math FS = 20000 # PWM载波频率:20kHz F_OUT = 50 # 基波频率:50Hz N = FS // F_OUT # 400点,每工频周期推进1点 M = 0.90 # 调制比,留一点死区损耗余量 def make_table(shift_rad): tbl = [] for i in range(N): duty = 0.5 + 0.5 * M * math.sin(2 * math.pi * i / N + shift_rad) ccr = int(duty * 1799) # 对应ARR=1799 ccr = max(0, min(1799, ccr)) tbl.append(ccr) return tbl for name, shift in [("A相", 0), ("B相", -2 * math.pi / 3), ("C相", 2 * math.pi / 3)]: print(f"// {name},相位偏移 {math.degrees(shift):.0f}°") tbl = make_table(shift) for i in range(0, N, 8): print(", ".join(str(x) for x in tbl[i:i+8]) + ",") print()

这段代码里N必须等于FS除以F_OUT,也就是400。这样CCR表每50μs推进一点,20ms走完一整圈,50Hz精确成立。调制比0.9意味着占空比在0.05到0.95之间摆动,留出的10%余量是为了给死区和下管最小导通时间腾空间。如果调制比拉到0.98,CCR接近ARR,下管可能没有足够时间完成关断,炸管风险急剧上升。

实际工程里我一般不用实时计算,直接用查表。STM32F103C8T6的Flash写满这三张表也只占2400字节左右,完全够用。如果你想把表尺寸压小,也可以只存一相表,另外两相用定点小数索引加插值,但代码复杂度上去了,收益却不大。新手阶段建议老老实实放三张独立表,出错时好排查。

2.2 STM32F103C8T6引脚功能分配:TIM1的6路互补输出怎么接

三相全桥需要6个开关管,也就是三组半桥。STM32F103C8T6里只有TIM1和TIM8是高级定时器,支持互补输出和硬件死区插入;而C8T6没有TIM8,所以只能用TIM1。这是选型上“没得选”但又刚好够用的地方。TIM1在APB2总线上,时钟72MHz,足够做20kHz甚至更高频率的SPWM。

默认映射下,TIM1_CH1、CH2、CH3分别在PA8、PA9、PA10,互补输出CH1N、CH2N、CH3N分别在PB13、PB14、PB15。这正好组成三组互补驱动信号:PA8/PB13驱动A相半桥,PA9/PB14驱动B相,PA10/PB15驱动C相。引脚分配表如下:

功能引脚说明
TIM1_CH1 / CH1NPA8 / PB13A相上桥臂 / 下桥臂
TIM1_CH2 / CH2NPA9 / PB14B相上桥臂 / 下桥臂
TIM1_CH3 / CH3NPA10 / PB15C相上桥臂 / 下桥臂
TIM1_BKINPB12刹车信号,急停用

引脚映射时有个细节:如果你想用重映射把CH1N挪到PA7,反而会和其他外设打架,建议直接用默认映射。PA8/PA9/PA10上桥臂接高端驱动的HIN,PB13/PB14/PB15下桥臂接LIN。市面上常见的IR2103、IR2110这类自举半桥驱动芯片,正好吃这一组互补信号。别把CH和CHN接反,否则上下管逻辑颠倒,轻则波形乱,重则直通炸管。上电前用万用表蜂鸣档核对一下PA8到驱动器HIN、PB13到LIN的走线,是值得养成的习惯。

2.3 死区时间怎么设:从功率管参数到DTG寄存器

死区的作用是防止同一桥臂上下管在切换瞬间同时导通。任何一个功率管都有开通延迟和关断延迟,栅极驱动芯片也有传播延迟,如果上管还没完全关断、下管就开始导通,母线电压直接短路,几微秒就能炸管。死区时间至少要大于“上管关断延迟最大值减去下管开通延迟最小值”,实际工程中再留一倍余量。

以常见的IRFP460 MOSFET为例,关断延迟典型值60ns到180ns,栅极电阻加到10Ω以上后关断更慢,取1μs死区是稳妥的。如果换IGBT,关断有拖尾电流,死区一般取2μs到3μs。STM32的死区时间由TIM1_BDTR寄存器的DTG字段控制,Tdts等于1/72MHz约13.9ns。这里有个很多人踩过的分段坑:DTG不是线性映射的,超过127就得换公式:

DTG范围死区时间计算公式例子
0 ~ 0x7FDTG[7:0] × TdtsDTG=72,得到1μs
0x80 ~ 0xBF(64 + DTG[5:0]) × 2 × TdtsDTG=128,得到1.78μs
0xC0 ~ 0xDF(32 + DTG[4:0]) × 8 × TdtsDTG=192,得到3.56μs
0xE0 ~ 0xFF(32 + DTG[4:0]) × 16 × TdtsDTG=224,得到7.1μs

标准库代码里直接把TIM_BDTRInitStructure.TIM_DeadTime设成72,对应1μs死区。如果你要2μs,DTG应该是144,但它落在0x80到0xBF区间,公式变成(64 + 144 - 128) × 2 × 13.9ns = 2.22μs,不是精确的2μs。这也是为什么很多老工程师说“死区寄存器写个数很容易,写对很难”。建议先确定目标死区,再反推DTG落在哪个区间,不要直接拿微秒数乘以72。

3. 在AD里搭最小系统与电源树:原理图到PCB的第一步

3.1 从STM32F103C8T6最小系统板原理图抄出的5个必接引脚

网上大量“STM32F103C8T6最小系统板”的原理图,核心就是五件事:VBAT、BOOT0、NRST、VDDA和去耦电容。VBAT必须接3.3V,否则备份域寄存器无法工作;BOOT0要经10kΩ下拉到GND,确保上电从Flash启动,而不是进ISP;NRST上拉10kΩ并并联0.1μF电容到地,防止复位引脚被干扰。VDDA和VSSA是模拟电源,不能直接并到VDD上完事,一般用磁珠隔离后再加1μF滤波电容,这直接影响到ADC采样和内部参考电压的稳定性。

晶振也是最小系统里容易翻车的一环。内部HSI只有8MHz,虽然可以PLL倍频到72MHz,但精度不够,SPWM载波会跟着漂,导致基波频率不稳定。做逆变电源必须外接8MHz晶振,配两个20pF负载电容。还有一个细节:STM32F103C8T6的OSC_IN和OSC_OUT引脚如果不用外部晶振,必须接地或悬空,不能接普通IO。资料包里如果给你的是“最小系统板原理图”而不是“最小系统+驱动”完整图,这部分就是你要自己补的功课。

去耦电容不要只放一个100nF了事。每个VDD/VSS引脚旁边都放一个100nF,靠近引脚放置,然后在电源入口再放一个10μF钽电容。很多人PCB打样回来程序跑飞、SPWM随机丢脉冲,查到最后就是去耦电容离引脚太远,高频噪声直接灌进MCU电源。这是看着小、影响大的细节。

3.2 电源树与AD原理图怎么生成PCB:位号、封装与网络标号

先把电源树理清,再动手画原理图。三相逆变电源的电源树一般是:输入直流母线(比如48V验证平台)先经过母线电容,一路进三相全桥功率级,另一路经过Buck降压到5V,再经AMS1117降到3.3V给MCU。控制电源和功率母线之间要有明显的分区,不要让3.3V的走线贴着母线的高频开关回路走。栅极驱动芯片的供电,低压验证平台可以直接从5V取,但上桥臂要靠自举电容供电,下桥臂直接给VCC就行。

在AD里从原理图生成PCB前,有三件事必须做。第一,Tools菜单下Annotate统一编号,检查位号有没有重复;很多从网上拼来的原理图,位号是乱的,生成PCB时网络会串。第二,检查封装,STM32F103C8T6是LQFP48,别画成TQFP48,两者的焊盘尺寸和引脚间距不同,焊上去虚焊很难查。第三,检查网络标号,三对互补PWM的标号别标反,A相CH1和CH1N必须成对出现。

AD里原理图生成PCB的路径是Design → Update PCB Document,但前提是你在PCB文件里已经设置了足够大的板框和原点。如果工程是“AD好几个原理图”拼在一起的,每个原理图页都要检查是否有悬空网络,悬空网络在PCB里表现为飞线乱飘,很容易被忽略。我一般会在生成PCB后,先按网络分类打开PCB面板,看GND网络有没有意外连接到功率地。

3.3 PCB布局与多边形填充:功率地、信号地与螺丝孔

三相逆变器的PCB布局核心是“功率回路短、控制回路远”。第一层先放母线电容和三个半桥,母线电容要尽可能靠近每个半桥的直流输入端,形成低感抗回路;第二层放栅极驱动芯片,驱动芯片要靠近对应的MOS管栅极,栅极走线越短,开关振铃越小;第三层才是MCU和信号电路,离功率区至少隔开一段距离。

功率地和控制地在很多方案里是分开的,最后在母线电容负极处单点连接。这样做是为了避免功率地线上的大电流瞬变耦合进模拟地。如果你在原理图里把GND网络直接连成一片,PCB上所有地都短在一起,示波器看输出电压时会有明显的高频毛刺。AD里做GND铺铜用Polygon Pour,注意设置网络间距,我一般把GND铜皮到其他网络的距离设为0.3mm,铺铜方式选Hatched,方便焊接和散热。

散热和固定孔也要提前规划。M3螺丝孔在PCB上一般是过孔3.2mm、焊环外径不小于5mm;如果用M2螺丝,孔径2.1mm、焊环外径不小于3.2mm。螺丝孔不要放在功率走线中间,否则会切断铜皮载流路径。散热方面,如果MOS管用的是TO-220封装,建议引脚间距和散热器位置在布局阶段就确定,不然画完板发现散热器顶住电容只能重画。

4. 软件落地:在Keil下建立工程并让TIM1输出三相互补SPWM

4.1 在Keil下建立STM32F103C8T6标准库工程模板

拿到源码包后,第一件事是建立工程模板,确认能编译、能下载,再动SPWM代码。常见做法是用标准外设库V3.5,配合CMSIS和启动文件。C8T6属于中密度产品,启动文件必须选startup_stm32f10x_md.s,选错启动文件的话程序一跑就进HardFault。工程目录我习惯这样组织:

Project/ ├── User/ │ ├── main.c │ └── stm32f10x_it.c ├── Core/ │ ├── startup_stm32f10x_md.s │ ├── core_cm3.c │ └── system_stm32f10x.c ├── Periph/ │ ├── inc/ │ │ ├── stm32f10x_gpio.h │ │ ├── stm32f10x_tim.h │ │ └── stm32f10x_rcc.h │ └── src/ │ ├── stm32f10x_gpio.c │ ├── stm32f10x_tim.c │ └── stm32f10x_rcc.c └── Project.uvproj

在Keil里新建工程时选STM32F103C8,然后在C/C++选项卡的Define里加上STM32F10X_MD和USE_STDPERIPH_DRIVER。前者告诉标准库你用的是中密度芯片,后者让库函数实现真正生效。漏掉这两个宏是新手最常见的问题,表现是编译报一堆undefined,或者库函数里全是空壳。Flash Download设置里勾选Reset and Run,下载完自动复位运行。

工程模板建好后,先写一个点灯程序确认GPIO和时钟没问题,再接PWM。这样后面出的问题都能定位到外设配置,而不是把工程环境问题和业务逻辑问题混成一锅粥。

4.2 TIM1初始化:20kHz载波、1μs死区与主要参数

TIM1初始化是这套软件的核心,参数全在代码里。PWM频率由72MHz分频决定:PSC=1,ARR=1799,输出频率等于72MHz除以2再除以1800,正好20kHz。20kHz高于人耳可闻范围,变压器和电感不会发出刺耳啸叫,是逆变电源的常用载波频率。

#include "stm32f10x_tim.h" void TIM1_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // 上桥臂:PA8/PA9/PA10 复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 下桥臂:PB13/PB14/PB15 复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_Init(GPIOB, &GPIO_InitStructure); } void TIM1_PWM_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // 72MHz / (1+1) = 36MHz,ARR=1799 → 20kHz TIM_TimeBaseStructure.TIM_Prescaler = 1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 1799; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // 三通道比较输出均使能,互补输出由硬件自动实现 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_Pulse = 900; // 初始占空比50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC2Init(TIM1, &TIM_OCInitStructure); TIM_OC3Init(TIM1, &TIM_OCInitStructure); // 死区1μs:DTG = 1μs / (1/72MHz) = 72,即0x48 TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime = 72; TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); TIM_Cmd(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); // 关键:使能主输出MOE }

最后那行TIM_CtrlPWMOutputs是高级定时器特有的步骤。TIM1必须在使能后额外打开主输出开关,否则6个引脚全部无输出。这个函数漏加了不会报错,但你会发现示波器上什么都没有。所有用TIM1/TIM8做PWM的人都在这里挂过至少一次。TIM_OSSRState和TIM_OSSIState控制空闲时输出状态,建议都设为Enable,保证刹车信号触发后输出到确定电平。

4.3 查表更新CCR:三相独立表与更新中断

PWM初始化完成后,剩下的工作就是每50μs更新一次CCR。我不用DMA,直接在TIM1更新中断里赋值。20kHz中断频率在72MHz主频下开销很低,而且三相表独立,逻辑清楚,出问题好查。如果你以后想把这个方案推到100kHz载波,再考虑DMA也来得及。

#define SPWM_POINTS 400 extern const uint16_t spwm_a[SPWM_POINTS]; extern const uint16_t spwm_b[SPWM_POINTS]; extern const uint16_t spwm_c[SPWM_POINTS]; volatile uint16_t spwm_idx = 0; void TIM1_UP_IRQHandler(void) { if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM1, TIM_IT_Update); uint16_t i = spwm_idx; TIM_SetCompare1(TIM1, spwm_a[i]); TIM_SetCompare2(TIM1, spwm_b[i]); TIM_SetCompare3(TIM1, spwm_c[i]); if (++spwm_idx >= SPWM_POINTS) { spwm_idx = 0; } } }

这段代码里spwm_idx每个PWM周期加1,加到400清零,工频周期精确等于400除以20kHz等于20ms。三张表分别对应0°、-120°、+120°相位,互差120度由表本身保证,不靠索引偏移,避免了400不能被3整除的误差。如果你改了SPWM_POINTS,必须保证它还是3的倍数吗?不需要,因为是三张独立表,每个表自己转一圈就是360°,任何点数都能工作。但点数会直接影响基波相位步进,建议保持整数倍PWM周期数。

调用这个中断前要配置NVIC并使能更新中断:

NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

到这里,PA8/PA9/PA10和PB13/PB14/PB15上应该能看到三组互补SPWM波形了。先把示波器探头夹在PA8和PB13上,如果看到两路反相且中间有一段同时为低的脉冲,说明死区生效。再分别看另外两组,确认三相互差120°后再接功率板,这是整个调试过程中最关键的安全动作。

5. 三相SPWM逆变电源避坑实录:5个最容易翻车的场景

5.1 一上电就炸管:死区设置没生效

现象:控制板单独测试PWM波形正常,一接功率板母线电压,保险丝直接烧断,MOS管炸裂。

原因:最常见的是主输出使能TIM_CtrlPWMOutputs没调用,导致TIM1输出引脚全部处于无效电平,驱动芯片上电瞬间输出不定态;另一个原因是死区时间设得太小,或者DTG落到了错误的分段区间,实际死区只有几百纳秒。还有一种隐蔽场景:你在BDTR里写了死区,但后来又调用了TIM_OCInitStructure覆盖了输出极性,把CH1N极性改成了反逻辑,互补变成同相,桥臂直通。

解决:先不接母线,用示波器双通道同时看CH1和CH1N,确认两路之间存在一个明显的“同时为低”的时间段。我习惯把死区时间调到1μs后,在示波器上放大到2μs每格,数一下两个下降沿之间有没有一格以上的间距。确认无误后再串一个白炽灯限流接母线电压,白炽灯在短路时限制电流,在正常工作时灯丝基本不亮,这是低压验证阶段最便宜的保命手段。

5.2 滤波后波形带刺:栅极回路和吸收电容

现象:LC滤波后正弦波整体形状出来了,但波形上有密密麻麻的高频毛刺,示波器上看起来像正弦波上面长了一层“草”。

原因:这些毛刺通常来自MOS管开关瞬间的di/dt和dv/dt,通过驱动回路或地平面耦合到输出端。栅极驱动走线过长、栅极电阻太小、母线电容离半桥太远,三个因素至少占一个。还有可能是你示波器探头的地线夹太长,测高频信号时探头本身就成了天线,这种情况下波形毛刺是假的,换短地弹簧探头再看。

解决:栅极电阻从10Ω起步,如果毛刺严重可以加到22Ω甚至33Ω,代价是开关损耗增加。在每个半桥的直流母线两端并一个100nF的CBB电容,接在功率管的漏源之间,吸收开关尖峰。滤波电感上并联一个RC吸收支路,典型值10Ω和10nF串联,能明显压低振铃。先改这三个地方,再考虑加共模电感。

5.3 STM32F103C8T6下载失败:BOOT0与NRST的坑

现象:Keil里显示No target connected,或者下载到一半校验失败,有时候按几下复位能连上,但成功率很低。

原因:BOOT0悬空导致上电时引脚电平不确定,芯片可能进入ISP模式;NRST被当作普通IO使用,外部接了电容太大导致复位拉不起来;还有可能是调试时PA15、PB3、PB4这些JTAG引脚被代码复用成PWM输出,调试口被占,程序跑起来后下载器掉线。

解决:BOOT0接10kΩ下拉到地,NRST只做复位用,不要省那个10kΩ上拉和0.1μF电容。如果已经因为代码复用调试口导致掉线,按住开发板NRST不松,点击Download后立刻松开,趁芯片复位窗口期内把新程序烧进去。这个“按住复位下载”的土办法,能救回九成被锁死的C8T6。如果还不行,把BOOT0拉高进串口ISP,用FlyMcu擦除整片Flash再拉回来。

5.4 三相互差不是120°:查表点数与相位偏移

现象:单相SPWM波形正常,但三相互差角度不对,比如A相和B相之间差了100°,C相又差了140°,负载电流明显不平衡。

原因:如果三相共用一张表、靠索引偏移实现相移,而表点数不是3的倍数,相位偏移就会产生累积误差。比如256点表,256除以3约等于85.33,取整后每相偏差0.5°,三相加起来误差更大。另一个原因是PCB上三相输出顺序接错,把B相和C相在端子上对调了,波形本身没问题,是人为接线问题。

解决:用三张独立表,相位直接写死在表数据里,从根上消除索引取整误差。接线前用万用表导通档确认驱动芯片输出到功率管栅极是一一对应关系。示波器上验证相序的方法是:同时测A相和B相滤波前的桥臂中点对地波形,看两个正弦包络过零点的间隔,50Hz下120°对应约6.67ms,前后误差不超过0.3ms就算正常。

5.5 轻载电压偏高:LC参数与假负载

现象:空载或轻载时,输出电压比满载时高出一截,甚至接近母线电压峰值,负载电阻换大后电压继续往上飘。

原因:三相整流电容负载或纯电容滤波负载在空载时没有放电回路,母线电容和滤波电容被充到峰值电压。还有一种情况是LC滤波器固有谐振点恰好落在低频段,轻微激励就起振。很多逆变器标称输出220V,结果空载一测电压飙到300多伏,吓人一跳。

解决:输出端加假负载电阻,Y型接法每相并一个几十瓦的功率电阻,让输出始终有一个最小负载电流,电压就被拉住了。假负载的功耗按输出功率的2%~3%选,比如1kW逆变器配20W到30W。如果加了假负载电压仍偏高,检查LC谐振频率,保证谐振点远低于基波且远离载波,通常取载波频率的二十分之一以下。

6. 用双通道示波器验证三相SPWM:从互补死区到效率初测

6.1 先看死区,再看相序

双通道示波器验证三相SPWM,顺序必须是“先单桥臂、再线电压、最后滤波输出”。单桥臂验证的是死区和互补逻辑:CH1接PA8,CH2接PB13,两个通道都设成DC耦合,触发选上升沿,时基放到2μs。你应该看到两路方波完全反相,且翻转沿之间有约1μs同时为低的平台。如果平台为零,立刻断电查BDTR寄存器,不要抱侥幸心理。这一步是整个系统上电前唯一能直观确认“不会炸管”的依据。

确认死区后,把探头移到A相桥臂中点(上管源极与下管漏极连接点)和B相桥臂中点,做减法运算通道,看线电压Uab波形。SPWM三相逆变器的线电压是带正负电平的阶梯波,包络呈正弦变化。此时不要看毛刺,只看包络形状是否连续、三组线电压幅值是否一致。用示波器的数学通道做Uab减去Ubc,可以间接得到Uca的波形,用来快速判断三相是否对称。

滤波后测量才是最终结果:在LC滤波电容两端测相电压,波形应该是光滑的正弦波。低压48V母线、调制比0.9时,滤波后线电压有效值在23V到27V区间,低于这个范围说明调制比没生效,高于这个范围说明空载泵升。用万用表真有效值档复核示波器的读数,避免示波器平均模式骗了你。

6.2 LC滤波参数与效率初测

滤波参数的选取有一个很实用的顺序:先定截止频率,再反推LC值。截止频率取载波频率的十分之一到二十分之一,20kHz载波对应1kHz到2kHz。常见组合是1mH电感加10μF CBB电容,截止频率约1.6kHz,对20kHz载波有约40dB的衰减,对50Hz基波几乎无损耗。

效率测试用最笨的办法:直流输入侧串联万用表电流档测母线电流,电压档测母线电压,两者相乘得到输入功率;输出侧接三相对称Y型电阻负载,测相电压有效值,代入公式3乘以电压平方除以负载电阻,得到输出功率。两者相除就是效率。20kHz硬开关条件下,MOSFET方案做到88%到94%是正常区间。如果低于85%,检查死区是否过大、栅极电阻是否拖慢了开关速度、母线电容是否ESR过大。想再往上提,就要研究SVPWM了,它和SPWM的核心区别是用六个基本电压矢量合成目标矢量,直流母线利用率能提高约15%,代价是算法复杂度和死区补偿难度都上了一个台阶。

我第一版做这套东西时最血泪的一条教训,是不要相信死区寄存器里写了个数就万事大吉。后来养成习惯:任何一次改板、改参数,上电接母线之前,先量三对互补波形,确认无贯穿再接功率板。哪怕只换了一个电阻值也要重新量一遍。这个习惯让后面所有调试都顺了很多。如果你刚拿到这类资料包,从最小系统板焊起,到三相波形全出来,中间最值得投入精力的就是死区和LC两个参数,把它们吃透,剩下的都是熟练活。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询