基于ARM的buck-boost拓扑双向DC-DC电源变换器资料 同步BUCK电路和同步BOOST电路进行级联,采用高性能32位ARM 芯片构建数字电源,能够根据输入电压和输出电压的大小关系,实现自动切换工作模式,将参数信息进行显示,并且可以实现稳压输出。
最近在折腾一个基于ARM的双向DC-DC电源项目,同步BUCK和BOOST电路搞级联玩自动升降压,挺有意思的。这货的核心逻辑就是根据输入输出电压关系自动切换工作模式,还能用屏幕显示实时参数。今天咱们从硬件拓扑到代码实现唠点干货。

先说电路结构,这玩意儿本质上就是两个同步整流电路背靠背连接。BUCK部分的MOS管Q1/Q2负责降压,BOOST部分的Q3/Q4负责升压。中间储能电感选型很关键,我用的铁硅铝磁环绕制,实测在300kHz开关频率下效率能到93%。这里有个坑要注意:两个电路的驱动相位必须错开,不然上下管直通烧芯片分分钟的事。
主控用的是STM32G474,这货的HRTIM高级定时器简直是为数字电源量身定制的。看这段PWM初始化代码:
c
// 配置互补PWM通道
hrtim1.Instance->sTimerxRegs[0].CMP1xR = 150; // 占空比初始值
hrtim1.Instance->sTimerxRegs[0].SETx1R = HRTIM_SET1R_SST;
hrtim1.Instance->sTimerxRegs[0].RSTx1R = HRTIM_RST1R_SRT1;
hrtim1.Instance->sTimerxRegs[1].CMP1xR = 150; // 互补通道
hrtim1.Instance->sTimerxRegs[1].SETx1R = HRTIM_SET1R_SST;
hrtim1.Instance->sTimerxRegs[1].RSTx1R = HRTIM_RST1R_SRT1;
这里的骚操作在于利用对称PWM生成方式,死区时间直接硬件生成。HRTIM的psc分频寄存器设到最高分辨率,能实现纳秒级死区调节,比普通定时器精准不止一个量级。

模式切换逻辑是核心算法,我的实现方案是用状态机+滞环比较。当Vin>Vout+0.5V时进BUCK模式,Vin
c
#define SAMPLES 64
uint32_t adc_oversample(void) {
uint32_t sum = 0;
for(uint8_t i=0; i<SAMPLES; i++){
sum += HAL_ADC_GetValue(&hadc1);
// 插入延时确保采样间隔大于RC时间常数
DWT_Delay(10);
}
return sum >> 4; // 64次平均等效提高2位分辨率
}
显示部分用的OLED屏,移植了UGUI库。这里有个坑爹问题:电源高频干扰导致SPI通信乱码。解决办法是软件SPI配合IO口复用,关键代码:
c
void SPI_Write(uint8_t data) {
for(int i=0; i<8; i++){
HAL_GPIO_WritePin(SPI_CLK_GPIO_Port, SPI_CLK_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, (data & 0x80) ? GPIO_PIN_SET : GPIO_PIN_RESET);
DWT_Delay(1); // 插入硬件延时
HAL_GPIO_WritePin(SPI_CLK_GPIO_Port, SPI_CLK_Pin, GPIO_PIN_SET);
data <<= 1;
DWT_Delay(1);
}
}
稳压算法用的增量式PID,但针对开关电源特性做了改进。加入输出电压二阶导数前馈,动态响应速度提升明显:
c
float pid_update(PID_TypeDef *pid, float setpoint, float measured) {
float error = setpoint - measured;
float d_input = measured - pid->last_measured;
// 计算微分项时用测量值变化代替误差变化
float d_term = pid->Kd * (d_input - pid->prev_d_input);
pid->prev_d_input = d_input;
// 前馈项加入二阶导数
float feedforward = pid->Kff2 * (d_input * d_input);
float output = pid->Kp * error + pid->Ki * pid->integral + d_term + feedforward;
// 抗积分饱和
if(output < pid->out_max && output > pid->out_min){
pid->integral += error * pid->Ki;
}
return output;
}
最后说几个玄学经验:布局时功率地和数字地之间用磁珠连接比0Ω电阻靠谱;环路补偿别迷信仿真,实际用动态负载测试更有效;PWM驱动电阻选51Ω时波形最干净。这玩意儿调了两个月,烧了五六个MOS管才稳定,现在满负载24V/5A运行稳如老狗,切换模式时电压波动能控制在0.8%以内。