简介:基于TI DSP2833X的移相全桥控制工程源码,面向电源变换器、电机驱动等电力电子领域的开发者和学习者,解决PWM移相全桥的工程实现与闭环控制问题。压缩包共45个文件、约266KB,以C源文件、ASM汇编、H头文件及CCS工程配置为主,同时包含编译生成的obj、out、map文件与宏定义、链接脚本等多种辅助文件,便于直接导入开发环境研读、编译和验证。已有1864人学习下载。代码对应HVPSFB工程,覆盖PWM模块初始化与频率/占空比/死区配置、移相波形生成、上下桥臂同步锁存、过流过压等故障检测,以及基于负载反馈的动态闭环调节等完整环节;汇编与C混合实现展示了DSP2833X外设编程和实时中断处理的典型方式。无论是初次接触移相全桥的工程师,还是希望优化控制算法、排查软开关调试问题的开发者,都能从这些代码中提取可复用的配置思路与逻辑框架。
1. 移相全桥控制:为什么F2802x的PWM移相需要跳出“调占空比”思维
做通信电源或充电桩DCDC的工程师,第一次拿到移相全桥(PSFB)的DSP源码时,最先不适应的就是:输出电压不再由PWM占空比直接决定,而由原边两个桥臂之间的移相角决定。你改CMPA寄存器改得再准,超前桥臂和滞后桥臂如果没有严格的相位基准,整机效率、ZVS软开关和电磁干扰全部会失控。这套基于TI DSP2802x(2833X系列同源)的HVPSFB工程,把PWM移相链路做在了ePWM模块的同步机制上,主桥臂用ePWM1产生中心对齐基准,滞后桥臂通过TBPHS寄存器装载移相量,再叠加死区模块和故障保护,最终在ISR里完成闭环。理解这套源码,等于理解了数字移相全桥最核心的时序骨架。
2. ePWM移相实现:中心对齐基准、相位同步与死区参数配置
2.1 移相量不等于占空比偏移,相位基准来自时基同步
移相全桥有四个开关管,对角导通时能量传递到副边。超前桥臂(Q1/Q2)和滞后桥臂(Q3/Q4)之间的相位差决定了原边电压的有效占空比。这里最容易误写的地方在于:你不是调整Q3的CMPA值来“减少占空比”,而是让ePWM2的时基相对ePWM1整体平移一段相位。
在F2802x上,ePWM模块支持通过同步输入信号装载TBPHS寄存器,实现两个PWM模块的相位锁定。ePWM1作为主模块,在计数器归零时发出同步输出信号(SYNCO);ePWM2作为从模块,收到同步信号后把TBPHS里的值装入计数器,随后与ePWM1保持固定的相位关系。这样得到的移相是周期级的精确平移,不会因为中断任务抖动而漂移。
中心对齐模式(CTRMODE = TB_COUNT_UPDOWN)在这里基本是必选。中心对齐的PWM波形对称,开关管应力小,且原边电流纹波比边沿对齐小一个量级。代价是同一频率下计数频率翻倍,等效的移相分辨率也翻倍,这对DSP的ePWM时基来说是完全可以接受的。
2.2 主从ePWM寄存器配置:TBPHS与同步链路
以下配置代码基于HVPSFB-DevInit_F2802x.c的初始化逻辑整理,目标开关频率100kHz,SYSCLKOUT取60MHz,时基时钟30MHz:
// HVPSFB-DevInit_F2802x.c 中 ePWM1(超前桥臂)初始化 #define EPWM_CLK_DIV EPWM_CLK_DIV_1 #define EPWM_HSP_CLK_DIV EPWM_HSP_CLK_DIV_2 // 30 MHz TBCLK #define PWM_PERIOD 149 // 中心对齐时,fs = 30MHz / (2*(149+1)) = 100kHz #define DEADTIME_TICKS 8 // 250ns 死区在30MHz下的近似值 // ePWM1 作为主模块:相位基准为0 EPwm1Regs.TBPRD = PWM_PERIOD; EPwm1Regs.TBPHS.bit.TBPHS = 0; // 主模块相位始终为0 EPwm1Regs.TBCTR = 0; EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // 中心对齐,0 -> TBPRD -> 0 EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 周期寄存器使用影子装载 EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 计数器归零时输出同步信号 EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 主模块不接收相位装载 EPwm1Regs.TBCTL.bit.HSPCLKDIV = EPWM_HSP_CLK_DIV; EPwm1Regs.TBCTL.bit.CLKDIV = EPWM_CLK_DIV; // 初始占空比50%,即 CMPA = TBPRD / 2 EPwm1Regs.CMPA.bit.CMPA = PWM_PERIOD >> 1; EPwm1Regs.CMPB.bit.CMPB = PWM_PERIOD >> 1;这段代码的关键在于SYNCOSEL选择TB_CTR_ZERO,它让ePWM1在计数器每次回到零时产生同步脉冲。PHSEN设为TB_DISABLE保证主模块自身不被打扰。CMPA和CMPB先各设50%,之后ISR里根据闭环计算结果改写CMPA即可改变有效占空比。
从模块ePWM2的配置才体现移相核心:
// ePWM2(滞后桥臂):从模块,装载TBPHS实现移相 #define PHASE_SHIFT_TICKS (PWM_PERIOD >> 1) // 初始180度移相 EPwm2Regs.TBPRD = PWM_PERIOD; EPwm2Regs.TBPHS.bit.TBPHS = PHASE_SHIFT_TICKS; // 从模块相位偏移量 EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // 使能相位装载 EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // 同步输入来自ePWM1的SYNCO EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm2Regs.TBCTL.bit.HSPCLKDIV = EPWM_HSP_CLK_DIV; EPwm2Regs.TBCTL.bit.CLKDIV = EPWM_CLK_DIV; EPwm2Regs.CMPA.bit.CMPA = PWM_PERIOD >> 1; EPwm2Regs.CMPB.bit.CMPB = PWM_PERIOD >> 1;PHSEN置位是移相生效的开关。TBPHS从150改为120、90时,滞后桥臂整体前移,移相角减小,原边等效占空比变大,输出功率上升。
2.3 死区模块配置:防止直通,同时保留软开关余量
全桥上下管必须存在死区。F2802x的ePWM死区模块位于比较单元和输出引脚之间,可以在边沿插入纯延时,也可以配合极性选择生成互补的带死区波形:
// 死区配置:ePWM1A / ePWM1B 互补输出 EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // 上升沿和下降沿都启用 EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HI; // ePWM1A高有效,ePWM1B反相 EPwm1Regs.DBRED.bit.DBRED = DEADTIME_TICKS; // 上升沿延时 8个TBCLK EPwm1Regs.DBFED.bit.DBFED = DEADTIME_TICKS; // 下降沿延时 8个TBCLKDB_ACTV_HI的含义是:ePWM1A输出信号高电平有效且不反相,ePWM1B信号经过死区模块后输出为互补的负逻辑。上下管切换时,DBRED让开启沿延后,DBFED让关闭沿提前,两者叠加形成一段两边都不导通的空白时间。死区过大虽然更安全,但会缩小有效占空比,并破坏ZVS的励磁电流条件,所以死区参数要和变压器原边结电容、管子关断延时刻意匹配,后面第4章单独展开。
3. HVPSFB工程源码拆解:ISR中VMC/PCMC控制环路与代码组织
3.1 从launch文件到源文件:工程结构映射
这套源码的目录结构保留了CCS工程的完整形态,源码包里的关键文件对应关系如下:
| 文件 | 职责 |
|---|---|
| HVPSFB-Main.c | 主循环、模式切换、SCI指令解析 |
| HVPSFB-DevInit_F2802x.c | 系统时钟、GPIO、ePWM、ADC外设初始化 |
| HVPSFB-DPL-ISR.asm | PWM中断服务程序,补偿器与移相量计算 |
| HVPSFB-Settings.h | 开关频率、死区、软硬件过流阈值宏定义 |
| PWM_PSFB_VMC_SR_Cnf.c | 电压模式(VMC)与同步整流配置 |
| ADC_SOC_Cnf.c | ADC触发源与SOC排序配置 |
| DAC_Cnf.c | 内置DAC输出,用于观测环路中间量 |
| SciCommsGui.c | SCI串口通信,配合上位机调节参数 |
| HVPSFB_VMC.launch / HVPSFB_PCMC.launch | CCS调试器启动配置,对应两种控制模式 |
.launch文件直接对应两套调试入口,之前有人把这两个文件当成普通配置文件删掉,结果是CCS每次都得手动重建target配置。VMC和PCMC两套启动配置共享同一份源文件,通过编译宏或者运行时的模式标志切换。
3.2 为什么ISR放在汇编文件里
HVPSFB-DPL-ISR.asm直接延续了TI数字电源库(DPLib)的工程风格。数字电源ISR要求确定的执行时间,C编译器在流水线调度上和汇编相比存在不可控的差异。INC、MOV、MAC类指令在F2802x上有固定的执行周期,TI在DPLib里把采样读取、误差计算、补偿器更新、PWM装载串联成一条流水,保证中断在数微秒内完成。这套源代码保留.asm后缀并不是历史包袱,而是为了让补偿器的执行周期可预测。
3.3 VMC与PCMC:两种控制模式的差异
电压模式(VMC)和峰值电流模式(PCMC)在源码中的区别主要体现在三处:补偿器输入量、PWM比较值来源、保护触发条件。
// PWM_PSFB_VMC_SR_Cnf.c 中控制回路更新逻辑(简化) // VMC 模式:用输出误差驱动 CMPA/CMPB,更新点位于 ZERO 事件 EPwm1Regs.CMPA.bit.CMPA = (Uint16)(PWM_PERIOD * dutyVmc); EPwm2Regs.CMPA.bit.CMPA = (Uint16)(PWM_PERIOD * dutyVmc); // PCMC 模式:电流比较器直接控制占空比,ISR 内只做相位微调 // 电流采样信号送入比较子模块,CMPA 由比较器值决定VMC下,环路计算出的dutyVmc直接映射到两路CMPA,移相角由闭环输出和限幅逻辑一起决定。PCMC下,原边峰值电流通过比较器即时终止当前开关周期,DSP的ISR只负责在周期开始时装载峰值电流参考值。PCMC的原边电流动态响应明显更快,但对电流采样噪声敏感,绕组不对称时容易产生占空比抖动。
3.4 ISR到移相角度的映射关系
在DPL-ISR中,补偿器输出的DutyCmd最终要换算为TBPHS装载值。中心对齐模式下的相位分辨率是半个时基周期,映射关系为:
// HVPSFB-DPL-ISR.asm 后半段逻辑的C语言还原 #define MAX_PHASE_TICKS PWM_PERIOD phase_target = (Uint16)(DutyCmd * MAX_PHASE_TICKS + 0.5f); EPwm2Regs.TBPHS.bit.TBPHS = phase_target; EPwm1Regs.ETCLR.bit.INT = 1; // 清除ePWM1中断标志DutyCmd的取值范围在0到1之间。当DutyCmd为0时,TBPHS为0,两桥臂同相同步,原边电压为零;当DutyCmd为1时,TBPHS为149,相当于180度移相,原边获得最大伏秒积。这个映射改起来很容易出错的是:不能用PWM_PERIOD >> 1作为上限,那是占空比50%的移相,不是180度。
4. 移相全桥参数整定:死区、ZVS与TZ故障保护
4.1 死区参数计算:从物理条件推导寄存器值
死区时间要覆盖三个部分:开关管关断延时td(off)、驱动芯片传输延时、以及开关管输出电容充放电时间。公式近似为:
#define VIN_MAX 400.0f // 最大输入电压 #define Q_out_nC 62.0f // MOSFET 输出电荷,单位 nC #define I_off_A 8.0f // 关断时刻原边电流 // 死区时间下限 = td_off + td_driver + (Q_out / I_off) #define DEADTIME_NS (120.0f + 60.0f + (Q_out_nC / I_off_A) * 1000.0f)以Q_out 62nC、关断电流8A计算,第三项约7.75ns,算上前级延时约190ns。实际工程我一般取250ns,把Gate驱动芯片的离散性覆盖掉。但死区取到400ns以上时,滞后桥臂的ZVS窗口会明显缩短,轻载效率曲线会掉。FPGA或CPLD方案里死区要单独做逻辑,而在DSP上直接改DBRED/DBFED寄存器即可,方便做温度补偿。
4.2 故障保护:ePWM的TZ联动而不是软件关断
过流保护只靠ISR里比较ADC值再关PWM是不可靠的,ADC采样有延迟,软件分支也有不确定性。F2802x的TZ(Trip-Zone)模块可以做到硬件级封锁,配置过一次之后,即使CPU跑飞,PWM引脚电平也会被强制拉死:
// 过流信号接入 TZ1 引脚,低电平触发保护 EPwm1Regs.TZSEL.bit.OSHT1 = 1; // TZ1 作为 one-shot 触发源 EPwm1Regs.TZSEL.bit.OSHT2 = 1; // TZ2 同时接入,冗余保护 EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // ePWM1A 强制为低 EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // ePWM1B 强制为低 EPwm1Regs.TZEINT.bit.OST = 1; // 触发后保持封锁,直到手动清除TZ_FORCE_LO把对应PWM引脚拉到安全电平,比用软件置位GPIO的方式快得多。故障恢复时,需要把TZCLR里的OST位置1,并等一个完整的开关周期再重新装载PWM。这个流程在TI的DSP2833X系列中间接演化而来,源码里把过压、欠压、过流分别映射到TZ1/TZ2,是值得沿用的配置。
4.3 闭环动态下的限幅顺序
移相角的限幅不能只在最后输出TBPHS时做,要在补偿器输出端限幅。ISR里执行顺序应该是:
err = vout_ref - vout; duty_raw = DPL_Compensate(err); // 补偿器输出 duty_lim = CLAMPL(duty_raw, 0.02f, 0.95f); // 先限制占空比斜率 phase_out = (Uint16)(duty_lim * MAX_PHASE_TICKS); EPwm2Regs.TBPHS.bit.TBPHS = phase_out;占空比下限取2%是为了让原边有足够的励磁电流维持ZVS过渡,如果直接限到零,轻载时会听到变压器间歇啸叫。上限95%则给死区留出完整时间,避免有效占空比把死区吃掉。
5. 波形验证与CCS调试:用eCAP和逻辑分析仪校准移相角
5.1 用HVPSFB_VMC.launch进入调试并观察关键变量
双击HVPSFB_VMC.launch会直接启动CCS调试会话,加载Project_Name.out。连接目标板后,在Expression窗口添加EPwm1Regs.TBCTR、EPwm2Regs.TBCTR、TBPHS和phase_target。两个TBCTR的时间差除以TBCLK周期就是实时移相角。如果phase_target在变但TBCTR没有跟住,检查EPwm2Regs.TBCTL的PHSEN是否被误清掉。
在VMC调试图里把运行模式切到PCMC时,需要重新加载HVPSFB_PCMC.launch,同时给PWM_PSFB_VMC_SR_Cnf.c中的模式标志重新赋值。launch文件的区别在于初始化脚本和断点预设不同,直接用错launch有时候会出现变量无法读取的情况。
5.2 用eCAP模块自测PWM移相时序
没有示波器时,F2802x的eCAP模块可以当简易PWM测量仪用。把ePWM2A映射到eCAP1输入引脚,配置上升沿捕获两次的差值:
// eCAP1 配置为测量 ePWM2A 的周期 ECap1Regs.ECCTL1.bit.CAP1POL = EC_RISING; ECap1Regs.ECCTL1.bit.CAP2POL = EC_RISING; ECap1Regs.ECCTL1.bit.CAPLDEN = EC_ENABLE; ECap1Regs.ECCTL2.bit.TSCTRSTOP = EC_RUN; ECap1Regs.ECCTL2.bit.SYNCI_EN = EC_DISABLE;连续读取两次捕获值后,差值等于一个PWM周期对应的计数长度。再对ePWM1A重复一次测量,两个上升沿的差值减去一个整周期,就能反推移相角。这个数字量直接和TBPHS寄存器里的值做比对,误差要小于2个TBCLK,如果偏大会偏了说明该看高边驱动供电了。
5.3 四通道观察时的判据
逻辑分析仪四通道分别接ePWM1A、ePWM1B、ePWM2A、ePWM2B,重点确认三件事:同桥臂两个通道之间的死区时间,要有明显的低电平间隔;ePWM1A和ePWM2A的上升沿间隔对应目标移相角;开关周期稳定没有抖动。这里最容易出现的问题是示波器探头地线夹不同步,导致两个通道看起来有几十纳秒的相位差,实际是测量回路引入的误动。把四个地线夹全部接到功率地母排的同一个点上再测。死区判断上,轻载时原边电流过零附近可能会有震荡毛刺,那是副边同步整流体二极管反向恢复造成的,和死区配置无关。
本文还有配套的精品资源,点击获取