1. DAB变换器数字控制系统概述
DAB(Dual Active Bridge)双有源桥变换器作为高频隔离型DC-DC变换器的典型拓扑,其数字控制系统的实现一直是电源工程师面临的挑战。基于TI DSP28335平台开发时,需要特别关注三个核心模块的协同工作:状态机管理、ADC采样中断处理和抗饱和PI算法实现。这套系统我在多个工业电源项目中实际应用过,最深的体会是——时序精度直接决定系统可靠性,1us的延迟差异都可能导致整机效率下降5%以上。
为什么选择DSP28335?这颗200MHz主频的C2000系列DSP在数字电源领域堪称经典。其内置的ePWM模块支持纳秒级分辨率,12位ADC的采样保持电路仅需60ns,特别适合DAB这种开关频率在100kHz以上的应用场景。不过硬件性能只是基础,真正的难点在于软件架构设计。下面我就结合自己踩过的坑,详细拆解各模块的实现要点。
2. 系统状态机设计与实现
2.1 状态定义与切换逻辑
DAB变换器必须包含的状态至少有以下四种:
c复制typedef enum {
SYS_INIT, // 系统初始化
STANDBY, // 待机模式
RUNNING, // 正常运行
FAULT // 故障保护
} SystemState;
volatile SystemState g_sysState = SYS_INIT;
这里使用volatile修饰全局状态变量是关键,因为它在中断和主循环中都会被访问。我曾遇到过因为忘记加volatile导致状态标志读取异常的诡异bug,系统会随机进入故障状态。
状态切换建议采用经典的switch-case结构,但要注意两点:
- 每个case块内必须包含完整的状态处理逻辑
- 状态切换时要考虑硬件状态的同步
c复制while(1) {
switch(g_sysState) {
case SYS_INIT:
InitPeripherals();
if(CheckPowerGood())
g_sysState = STANDBY;
break;
case STANDBY:
if(EnableSignal) {
SoftStart();
g_sysState = RUNNING;
}
break;
case FAULT:
HandleFault();
if(FaultCleared)
g_sysState = SYS_INIT; // 必须回到初始化重新配置
break;
}
}
2.2 故障保护机制实现
DAB变换器最怕的就是直通炸管,我们的保护机制必须满足:
- 故障检测响应时间<500ns
- 硬件PWM关断优先于软件处理
- 故障恢复需要手动复位
具体实现时,要充分利用DSP28335的Trip Zone功能:
c复制void InitTZModule() {
EALLOW;
EPwm1Regs.TZSEL.bit.OSHT1 = 1; // 启用Trip1信号
EPwm1Regs.TZCTL.bit.TZA = 2; // 故障时强制PWM输出低
EPwm1Regs.TZCTL.bit.TZB = 2;
EDIS;
}
重要提示:故障状态退出时,必须按照"清除标志→复位PWM→重新初始化"的顺序操作。直接跳转到RUNNING状态会导致二次故障。
3. ADC采样中断的工程实践
3.1 双缓冲数据读取技巧
DSP28335的ADC模块有个设计缺陷——结果寄存器不是双缓冲的。这意味着如果在转换过程中读取数据,可能得到错误值。我的解决方案是:
c复制#pragma CODE_SECTION(adc_isr, "ramfuncs");
__interrupt void adc_isr(void) {
static struct {
Uint16 input_voltage;
Uint16 output_current;
Uint16 temp_sensor;
} adc_buff;
// 移位操作消除ADC噪声
adc_buff.input_voltage = AdcResult.ADCRESULT0 >> 4;
adc_buff.output_current = AdcResult.ADCRESULT1 >> 4;
// 必须的寄存器操作序列
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;
AdcRegs.ADC_ST_FLAG.bit.INT_SEQ1_CLR = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
memcpy(&g_real_time_data, &adc_buff, sizeof(adc_buff));
}
这里有几个关键点:
- 使用结构体打包所有ADC通道数据
- 通过memcpy实现原子操作(DSP28335支持32位总线操作)
- 中断函数放在RAM中执行(CODE_SECTION指令)
3.2 采样时序同步技巧
DAB变换器需要严格的PWM-ADC同步,推荐配置方案:
c复制void ConfigAdcPwmSync() {
// ADC在PWM周期中点触发采样
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能SOC
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // 计数器等于CMPB时触发
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 每个事件都触发
EPwm1Regs.CMPB = EPwm1Regs.TBPRD / 2; // 设置在中点
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 采样窗口=16个SYSCLK周期
AdcRegs.ADCTRL3.bit.ADCCLKPS = 3; // ADC时钟分频
}
实测表明,这种配置可以将采样抖动控制在±5ns以内,远优于软件触发的±200ns水平。
4. 抗饱和PI算法深度优化
4.1 算法实现细节
普通PI控制在输出饱和时会产生严重的积分饱和现象。我们的改进方案:
c复制typedef struct {
float Kp;
float Ki;
float integral;
float out_max;
float out_min;
float Ts; // 采样周期
} AntiWindupPI;
float pi_calculate(AntiWindupPI *pi, float error) {
float output = pi->Kp * error + pi->integral;
// 抗饱和条件判断
if((error > 0 && output >= pi->out_max) ||
(error < 0 && output <= pi->out_min))
{
return CLAMP(output, pi->out_min, pi->out_max);
}
// 积分项更新(带泄漏因子)
pi->integral += pi->Ki * error * pi->Ts * 0.98f;
return output;
}
这个算法有三个创新点:
- 输出饱和时停止积分累积
- 引入0.98的泄漏因子防止积分漂移
- 显式考虑采样周期Ts
4.2 参数整定经验
根据DAB的动态特性,推荐以下整定步骤:
- 先设Ki=0,逐步增大Kp直到系统出现等幅振荡
- 取振荡周期Tu,临界增益Ku
- 按Ziegler-Nichols公式:
- Kp = 0.6*Ku
- Ki = 2*Kp/Tu
- 最终微调时,输出限幅值建议设为额定值的120%
实测数据:在400V/10A的DAB平台上,该算法使负载阶跃响应时间从15ms缩短到8ms,超调量从12%降至5%以内。
5. PWM模块配置要点
5.1 死区时间硬件配置
永远不要用软件实现死区!正确的硬件配置方法:
c复制void InitEPwm() {
EPwm1Regs.TBPRD = SYSTEM_FREQ / SWITCHING_FREQ - 1;
// 死区配置(单位:PWM时钟周期)
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIGH;
EPwm1Regs.DBFED = DEADTIME_NS * SYSTEM_FREQ / 1000;
EPwm1Regs.DBRED = DEADTIME_NS * SYSTEM_FREQ / 1000;
// 相位偏移实现移相控制
EPwm1Regs.TBPHS.half.TBPHS = PHASE_SHIFT;
EPwm1Regs.TBCTL.bit.PHSEN = TB_ENABLE;
}
死区时间计算公式:
code复制DBFED = (期望死区时间ns × 系统频率MHz) / 1000
例如:100ns死区 @200MHz → (100×200)/1000 = 20
5.2 调试避坑指南
- 示波器探头要使用差分探头测量上下管GS电压
- 首次上电前,先用低压电源(如30V)验证时序
- 死区时间建议从理论值的1.5倍开始调试
- 开关管栅极电阻影响上升沿,建议用10-22Ω
我曾经犯过的错误:没有考虑PCB走线延迟,按芯片手册配置的死区时间,实际测量发现少了15ns,导致桥臂直通。现在都会预留至少20%的余量。
6. 系统集成与实测数据
将各模块整合后,主程序架构如下:
c复制void main() {
InitSystem();
while(1) {
StateMachineHandler();
if(g_sysState == RUNNING) {
float error = g_ref_voltage - g_real_time_data.output_voltage;
float duty = pi_calculate(&g_pi_ctrl, error);
UpdatePwmDuty(duty);
}
WatchdogFeed();
}
}
实测性能指标(输入400V,输出200V/5A):
| 参数 | 数值 |
|---|---|
| 效率 | 95.2% |
| 电压调整率 | ±0.8% |
| 负载调整率 | ±1.2% |
| 动态响应时间 | <10ms |
这套程序框架已经在多个工业电源产品中验证,最长的无故障运行记录达到3.8万小时。最后分享一个血泪教训:一定要在PCB布局阶段就考虑好ADC采样走线,我有次因为采样路径经过MOSFET驱动线,导致ADC值有200mV的开关噪声,不得不重新打板。现在都会严格执行:
- ADC走线与功率线垂直交叉
- 模拟地单点连接到功率地
- 采样电阻直接接入DSP不经过接插件
