1. 项目概述:基于STM32的PWM开关电源控制方案
这个项目本质上是用STM32F103ZET6这颗工业级MCU来实现一个数字化的开关电源控制系统。相比传统的模拟控制方案,数字控制具有参数可编程、响应速度快、抗干扰能力强等显著优势。我在电源行业工作多年,亲眼见证了数字电源如何逐步取代模拟方案的过程。
STM32F103ZET6作为Cortex-M3内核的经典型号,其定时器资源特别适合做PWM生成。项目中我们会用到它的高级定时器TIM1,配合内置的ADC采样反馈电压,实现完整的闭环控制。这种方案特别适合中小功率(100W以内)的反激式、Buck/Boost等拓扑结构的开关电源设计。
2. 硬件设计关键点解析
2.1 STM32F103ZET6外设配置
这颗芯片有3个高级定时器(TIM1/8)和4个通用定时器(TIM2-5),我们选择TIM1_CH1/CH2产生互补PWM信号。需要特别注意:
- 死区时间必须配置(通常50-100ns)
- PWM频率建议设置在20-100kHz范围
- 使用重装载值ARR控制频率,捕获比较寄存器CCR控制占空比
c复制// PWM初始化示例代码
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Period = 999; // 100kHz @72MHz
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 50%占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
2.2 功率电路设计要点
对于反激式拓扑(最常用的隔离方案):
- 变压器设计最关键:AP法计算磁芯尺寸
- 原边MOSFET选型要注意Vds耐压和Qg参数
- 输出整流二极管建议用肖特基(Schottky)
- RCD吸收电路参数需要精确计算
重要提示:调试时务必先断开主功率回路,用示波器确认PWM信号正常后再上电!
3. PI调节算法实现
3.1 数字PI控制器设计
离散化后的PI算法公式:
code复制u(k) = Kp*e(k) + Ki*Σe(j) + u0
其中:
- e(k) = Vref - Vfb(k) 当前误差
- Kp: 比例系数
- Ki: 积分系数 = Kp*Ts/Ti
- Ts: 采样周期
c复制// PI调节器代码实现
typedef struct {
float Kp;
float Ki;
float max_output;
float integral;
} PI_Controller;
float PI_Update(PI_Controller* pi, float error) {
pi->integral += error;
// 抗积分饱和
if(pi->integral > pi->max_output/pi->Ki)
pi->integral = pi->max_output/pi->Ki;
else if(pi->integral < -pi->max_output/pi->Ki)
pi->integral = -pi->max_output/pi->Ki;
float output = pi->Kp * error + pi->Ki * pi->integral;
// 输出限幅
if(output > pi->max_output) output = pi->max_output;
else if(output < 0) output = 0;
return output;
}
3.2 参数整定方法
推荐采用工程整定法:
- 先设Ki=0,逐渐增大Kp直到系统出现等幅振荡
- 记录此时的临界增益Kc和振荡周期Tc
- 根据Ziegler-Nichols公式:
- Kp = 0.45*Kc
- Ti = 0.83*Tc
- 微调参数直到响应曲线满意
4. 系统集成与调试技巧
4.1 软件架构设计
建议采用状态机模式:
mermaid复制stateDiagram
[*] --> Idle
Idle --> Startup: 使能信号
Startup --> Running: 软启动完成
Running --> Fault: 过流/过压
Fault --> Idle: 故障清除
实际代码实现:
c复制typedef enum {
STATE_IDLE,
STATE_STARTUP,
STATE_RUNNING,
STATE_FAULT
} PSU_State;
void PSU_StateMachine(PSU_State* state) {
static uint32_t soft_start_cnt = 0;
switch(*state) {
case STATE_IDLE:
if(enable_signal) {
*state = STATE_STARTUP;
soft_start_cnt = 0;
}
break;
case STATE_STARTUP:
// 软启动:占空比从0%线性增加到目标值
pwm_duty = soft_start_cnt * target_duty / SOFT_START_TIME;
if(++soft_start_cnt >= SOFT_START_TIME) {
*state = STATE_RUNNING;
}
break;
case STATE_RUNNING:
if(over_current || over_voltage) {
*state = STATE_FAULT;
PWM_Disable();
}
break;
case STATE_FAULT:
if(fault_cleared) {
*state = STATE_IDLE;
}
break;
}
}
4.2 调试常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| PWM无输出 | 定时器未使能/GPIO配置错误 | 检查TIMx_CR1和GPIO复用功能 |
| 输出电压振荡 | PI参数不合适 | 减小Kp或增加Ti |
| 轻载不稳定 | 进入DCM模式 | 增加假负载或调整补偿 |
| MOSFET发热严重 | 死区时间不足/驱动能力不够 | 调整死区时间/加强驱动 |
5. 进阶优化方向
5.1 加入前馈控制
在PI基础上加入输入电压前馈:
code复制Duty = PI_output + Kff*Vin
可显著改善输入电压突变时的动态响应。
5.2 数字滤波处理
对ADC采样值进行滑动平均滤波:
c复制#define FILTER_LEN 8
float moving_avg(float new_sample) {
static float buffer[FILTER_LEN] = {0};
static uint8_t index = 0;
static float sum = 0;
sum -= buffer[index];
buffer[index] = new_sample;
sum += new_sample;
index = (index + 1) % FILTER_LEN;
return sum / FILTER_LEN;
}
5.3 效率优化技巧
- 同步整流:用MOSFET替代肖特基二极管
- 变频控制:轻载时降低开关频率
- 数字补偿:根据负载自动调整PI参数
这个项目最让我有成就感的部分是看到数字控制带来的灵活性——只需修改代码就能调整电源特性,这在模拟方案中是不可想象的。不过也要提醒新手,功率电路布局布线非常关键,我的经验是:大电流路径尽量短而宽,控制信号远离功率回路,地平面分割要合理。
