在开关电源从模拟环路切换到数字控制之后,电源数字控制算法的核心不再只是一个 PID 公式,而是由采样、补偿、PWM 调制、状态机、保护和通信共同组成的一套控制逻辑。实际项目中,很多人把 MCU 或者 DSP 上的控制代码写完了,但输出电压纹波大、动态响应差、环路振荡,甚至上电就保护,问题往往不在某个公式,而在算法和硬件链路没有对齐。本文从控制对象的理解开始,逐步拆解数字电源中的采样、离散化、控制律、状态机和故障处理,并给出可落地的代码片段和排查思路。
1. 先理解数字控制算法在电源里的完整链路
1.1 数字控制与模拟控制的差别
传统模拟电源里,输出电压误差由运算放大器和阻容网络组成的补偿器处理。补偿器的比例、积分、微分特性由电阻电容值决定。一旦硬件焊接完成,参数就很难在线调整,还会受温度漂移影响。数字控制把误差放大、补偿计算、限幅和 PWM 调制都移到了 MCU 或 DSP 内部,ADC 负责把电压电流转换回数字量,控制算法输出新的占空比或开关频率。
两者最关键的区别是“信息处理方式”不同。模拟控制是一个连续时间系统,数字控制则是按固定周期采样和计算的离散系统。采样周期、ADC 分辨率、PWM 分辨率、控制代码执行时间,都会进入环路特性。
| 对比项 | 模拟控制 | 数字控制 |
|---|---|---|
| 误差处理 | 运放与阻容网络 | ADC 采样后由软件计算 |
| 参数调整 | 改电阻电容 | 改软件参数 |
| 温度漂移 | 明显 | 相对稳定 |
| 非线性控制 | 实现困难 | 可以在软件中分模式处理 |
| 抗干扰 | 速度快但不易复杂滤波 | 可用数字滤波但存在延迟 |
| 故障记录 | 难 | 可以保存故障现场数据 |
1.2 一条控制环路要经过哪些环节
以常用的 Buck DC-DC 为例,数字控制的基本链路由以下环节组成:输出电压或电感电流经过采样网络进入 ADC,ADC 输出数字量后,控制算法读取参考电压和反馈量,计算误差并生成控制量,控制量再交给数字 PWM 模块转换成驱动波形,驱动功率开关管,最终改变电感电流和输出电压。
这个链路中,采样、计算、输出都发生在同一个控制周期内。因此,控制周期不等于开关周期,它可能等于一个或多个 PWM 周期。实际设计时,要把 ADC 采样时刻、PWM 更新时刻、控制中断优先级统一考虑。
LDO 也属于电源,但它是线性稳压,不需要高频开关动作,也就没有这套离散补偿算法。数字控制算法主要针对 DC-DC、PFC、LLC、反激、移相全桥等开关电源。
1.3 数字电源中的算法不止 PID
很多人提到数字电源就想到 PID,但真实工程里的控制算法通常是一组算法族。
常见模块包括:
- 电压环和电流环的 PI/PID 补偿。
- 峰值电流或平均电流控制。
- PFC 中的输入电压前馈和电流参考计算。
- LLC 或移相全桥的频率调节和相位调节。
- 多模块并联时的均流算法。
- 软启动和突发降功率。
- 过压、过流、过温保护逻辑。
- 模式切换状态机。
理解数字控制算法,不能只看一个控制公式,要把整个控制逻辑链路看完整。
2. 从被控对象到离散化:先理解控制对象再写代码
2.1 用 Buck 电路理解被控对象
数字控制器的设计对象是“控制量到输出量”的传递函数。Buck 电路工作在连续电感电流模式时,忽略寄生参数,控制量到输出电压的近似传递函数可以写成:
Gvd(s) = Vin / (L*C*s^2 + (L/R)*s + 1)其中 Vin 是输入电压,L 是电感,C 是输出电容,R 是负载电阻。这是一个典型的二阶低通特性。频率较低时,输出对占空比变化的增益接近 Vin;频率升高后,LC 谐振峰附近增益会变化,相位也会快速下降。
如果采用电流内环控制,被控对象会从二阶降为一阶,电压外环的补偿设计会更容易。这也是大多数数字电源会采用“电流内环 + 电压外环”结构的原因。
2.2 补偿器不是越强越好
只有补偿器让整个环路满足稳定条件,系统才能真正工作。环路增益通常写成:
T(s) = Gc(s) * Gvd(s) * H(s)其中 Gc(s) 是补偿器,H(s) 是反馈分压或采样比例。闭环系统需要足够的相位裕度和增益裕度。一般会保留 45 度到 60 度的相位裕度,带宽也不能盲目拉高。带宽太高会把采样噪声和开关噪声放大,导致输出抖动或振荡。
所以在数字电源里,补偿器的目标是让系统在目标带宽内增益稳定,在开关频率附近快速衰减,而不是单纯把 Kp 调大。
2.3 连续 PID 到离散 PID 的基本逻辑
连续 PID 的标准形式是:
u(t) = Kp * e(t) + Ki * ∫e(t)dt + Kd * de(t)/dt数字控制必须按离散周期执行,于是用采样周期 Ts 把积分和微分近似化。一个位置式 PI 控制器可以写成:
u(k) = Kp * e(k) + Ki * Ts * sum(e(i))为了避免累加项无限增长,工程里更常用增量式 PI:
du(k) = Kp * (e(k) - e(k-1)) + Ki * Ts * e(k) u(k) = u(k-1) + du(k)增量式的好处是控制量在前后两个周期之间只做小的变化,即使误差突变,也不会直接跳变到饱和值。积分部分仍然需要限幅,否则长期误差存在时,累加量会让输出长时间饱和。
3. 一个最小数字电源环路:从采样到 PWM 的代码骨架
3.1 同步采样和 ADC 转换
开关电源在开关管导通和关断瞬间,电压和电流信号包含大量高频毛刺。如果 ADC 在任意时刻采样,结果很容易受到开关噪声干扰。常见的做法是把采样时刻对齐到 PWM 中心点或关断段时间窗口。
下面是一个简化示例,在 ADC 完成中断里读取电压:
/* 由 PWM 触发 ADC 启动,在 ADC 完成中断中读取结果 */ volatile uint8_t ctrl_flag = 0; volatile uint16_t vout_adc_value = 0; void adc_complete_isr(void) { vout_adc_value = adc_read_channel(ADC_CH_VOUT); ctrl_flag = 1; }实际操作中,如果 MCU 支持 PWM 触发 ADC,启动时刻应该配置为 PWM 周期内噪声最小的位置。采样完成后再置位控制标志,避免在主循环里反复查询 ADC 状态。
3.2 在中断里执行控制律
数字电源的控制律必须在一个固定控制周期内完成。如果放在主循环,主循环里的一句延时或一条打印语句就会造成控制周期抖动。标准做法是控制中断优先级最高,中断里只做必要计算和 PWM 更新。
void control_isr(void) { float vout; float duty; float vref = 12.0f; if (!ctrl_flag) { return; } ctrl_flag = 0; vout = adc_to_voltage(vout_adc_value); duty = voltage_pi_update(vref, vout, duty); duty = clamp_f32(duty, 0.05f, 0.95f); pwm_set_duty(PWM_CH_MAIN, duty); }这里需要注意,duty 是上一周期计算出来的控制量,在新周期里既作为输入也作为输出保存。min 和 max 限幅不能随意设置,要结合 PWM 死区和最小脉宽要求。Buck 电路允许较高占空比,但 LLC 或反激电路对最大占空比通常有严格限制。
3.3 软启动与模式切换状态机
数字电源不能一上电就直接给满占空比,否则输出电容充电电流过大,容易触发过流保护或损坏器件。常见做法是用状态机管理上电、软启动、正常运行和故障恢复。
enum PowerState { STATE_STANDBY, STATE_SOFT_START, STATE_RUN, STATE_FAULT }; enum PowerState power_state = STATE_STANDBY; void power_state_machine(void) { switch (power_state) { case STATE_STANDBY: if (start_enable()) { soft_start_init(); power_state = STATE_SOFT_START; } break; case STATE_SOFT_START: soft_start_ramp(); if (vout_ready()) { power_state = STATE_RUN; } break; case STATE_RUN: if (fault_detected()) { fault_handler(); power_state = STATE_FAULT; } break; case STATE_FAULT: if (fault_clear_cmd()) { power_state = STATE_STANDBY; } break; } }状态机并不复杂,但决定了保护之后如何恢复、软启动是否重新执行、故障代码是否保留。生产环境里,故障状态不能因为一次电压尖峰就反复重启,也不能在恢复条件不满足时一直死锁。
4. 工程里可以落地的数字 PID 实现
4.1 增量式 PI 的完整 C 代码
下面的代码是一个工程里常见的增量式 PI 控制器,带输出限幅和积分限幅。实际使用时,需要把 float 替换成 MCU 支持的定点格式,尤其是没有硬件浮点单元的芯片。
typedef struct { float kp; float ki; float dt; float integral; float out_max; float out_min; float prev_error; } PiController; float clamp_f32(float value, float low, float high) { if (value > high) { return high; } if (value < low) { return low; } return value; } float pi_update(PiController *pi, float ref, float fb) { float err = ref - fb; float proportion = pi->kp * err; float d_out; float out; /* 先计算未限幅的控制量,再决定是否进入积分 */ d_out = proportion + pi->ki * pi->integral; out = d_out; /* 条件积分:只在控制量未饱和时累加积分 */ if (out < pi->out_max && out > pi->out_min) { pi->integral += err * pi->dt; } else { /* 饱和时停止积分,避免积分饱和 */ } pi->integral = clamp_f32(pi->integral, pi->out_min, pi->out_max); pi->prev_error = err; out = proportion + pi->ki * pi->integral; out = clamp_f32(out, pi->out_min, pi->out_max); return out; }这段代码的关键点有三个。第一,积分项只在控制量未饱和时累加。第二,积分限幅和输出限幅要单独处理,不能直接复用同一个变量。第三,PI 输出的单位必须和 PWM 模块一致,如果 PWM 寄存器需要 0 到 1000 的整数,控制算法输出就要对应到这个范围。
4.2 为什么积分饱和必须处理
如果参考电压突然升高,误差长时间保持很大,积分项会持续增大。一旦误差反向,积分项仍然很大,输出要等积分回落才能退出饱和,造成明显过冲。条件积分是缓解这个问题的常用手段,但它不能替代合理的软启动和限幅设计。
4.3 控制参数的影响速查
| 参数 | 主要作用 | 调大趋势 | 调小趋势 | 典型问题 |
|---|---|---|---|---|
| Kp | 加快响应 | 响应变快,增益提高 | 响应变慢 | Kp 过大会振荡 |
| Ki | 消除稳态误差 | 低频增益提高 | 稳态误差恢复慢 | Ki 过大会低频振荡 |
| Kd | 阻尼变化趋势 | 抑制过冲 | 阻尼变弱 | 对采样噪声敏感 |
| 控制周期 Ts | 每次计算的间隔 | 相位裕度下降,抗噪减弱 | 计算负担增大 | 周期必须固定 |
| 输出限幅 | 限制最大占空比 | 动态范围宽 | 负载能力受限 | 限幅太小导致动态响应差 |
实际项目中,不要直接在硬件上盲调 Kp 和 Ki。先根据控制对象的模型做仿真,得到初始参数后再上电源平台验证,效率会高很多。
5. 几种常见电源拓扑的数字算法要点
5.1 反激电源:峰值电流与轻载控制
反激电源在开关管导通时存储能量,关断时向副边释放能量。数字控制通常采用峰值电流控制或准谐振控制。在轻载时,连续开关会造成开关损耗高,所以要增加突发模式或降频模式。
常见的做法是定义轻载阈值,当负载电流低于阈值时,控制状态机切换到轻载模式,减小开关频率或只输出少量开关脉冲。进入和退出轻载模式都要加迟滞,避免负载在阈值附近抖动。
5.2 PFC 平均电流控制
PFC 的目标是让输入端电流波形跟随输入电压波形,同时调整输出电压。数字 PFC 的电流参考通常由输出电压误差和输入电压前馈共同生成,大致关系为:
i_ref = K * v_err * vin_feedforward其中 v_err 是输出电压误差补偿器的输出,vin_feedforward 根据输入电压瞬时值调整电流参考的幅度。电流内环再通过平均电流控制器调节占空比,使实际电感电流的平均值接近 i_ref。
这类算法对 ADC 同步性要求高,输入电压采样、电感电流采样和 PWM 控制必须在一个控制周期内完成,否则功率因数校正效果会明显下降。
5.3 LLC 与移相全桥:频率或相位控制
LLC 和移相全桥不是直接调占空比,而是调开关频率或桥臂之间的移相角。数字算法要解决的问题包括增益曲线管理、最低最高频率限制、死区时间配置以及工作模式切换。
调频控制时,输出电压偏低通常要降低开关频率以增加增益,但这个方向不是所有负载点都单调。必须在软件里根据工作区间选择正确的调节方向,并增加频率变化率限制,防止过快的频率变化引起输出抖动。
5.4 多模块并联均流
多个电源模块并联时,由于各模块输出电压采样误差和线路压降不同,电流分配很难完全均衡。常见的数字均流方法有两种。
一种是无互联线的下垂法。每个模块输出特性曲线人为加入下垂斜率,负载电流增大时输出电压轻微下降,从而自然均衡电流。优点是简单,但输出电压精度会下降。
另一种是主动均流。各模块通过均流总线交换电流信息,控制器将本模块电流和平均电流的差值补偿到电压参考中。数字控制里,均流误差会经过 PI 补偿后叠加到电压参考,并且不能破坏原有电压环稳定性。
6. 常见坑和排查链路
6.1 异常现象与原因速查表
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 带载后输出振荡 | 相位裕度不足或控制参数过强 | 查看输出电压波形和占空比波形 | 降低 Kp,或减小环路带宽 |
| 上电瞬间过流保护 | 软启动过快或积分初始值不对 | 查看软启动阶段占空比上升曲线 | 延长软启动时间,降低初始占空比 |
| 轻载时啸叫 | 频率落入可听噪声范围 | 用示波器测量开关频率 | 增加轻载模式频率下限 |
| 输出有大纹波毛刺 | ADC 采样点不对 | 检查 PWM 触发 ADC 的采样时刻 | 把采样点移到开关噪声最小窗口 |
| 调节方向反了 | PWM 极性配置错误 | 给占空比固定值观察输出变化 | 确认高电平有效还是低电平有效 |
| 两个并联模块电流不均衡 | 均流环路参数不正确 | 比较两路电流采样值 | 调整均流 PI,检查采样增益一致性 |
6.2 从现象倒推的排查顺序
遇到问题不要先改参数。先按下面顺序排查:
- 确认输入电源、负载、探头连接是否正确。
- 确认 ADC 原始值是否和万用表读数一致。
- 确认采样时刻是否在 PWM 噪声区之外。
- 确认 PWM 极性、死区时间和输出引脚配置。
- 确认控制周期是否固定,中断里是否有阻塞操作。
- 确认控制量单位是否和 PWM 寄存器匹配。
- 确认输出限幅和积分限幅是否合理。
- 确认保护阈值是否太灵敏。
- 最后再调整 PID 参数。
6.3 调试阶段要保留现场数据
数字电源的优势是可记录现场。调试时可以把每个控制周期结束后采集到的 ADC 原始值、电压标定值、误差、占空比和故障标志通过串口导出,也可以写到 RAM 环形缓冲区。
实测中常见的问题场景是:输出电压波形看起来正常,但故障偶尔误触发。如果没有故障记录,根本无法确认是保护阈值问题还是采样毛刺问题。加入日志后,再配合上位机分析,才能定位到具体事件。
7. 学习环境与生产环境的关键差异
7.1 开发板原型如何快速验证
学习阶段可以用支持数字电源开发的 MCU 评估板,先把 Buck 电路跑起来。推荐按三个步骤验证:第一步,用固定占空比测试 PWM 输出和驱动波形;第二步,用开环方式调整输出到目标电压附近;第三步,再接入闭环 PI 控制器。
示波器至少要观察两路信号:输出电压和电感电流。负载用电子负载做阶跃,观察输出电压过冲和恢复时间。高压环境下,要用隔离探头或差分探头,不能用普通探头直接测量高压侧。
7.2 生产环境还要补哪些能力
开发板能跑通距离产品化还有很大距离。生产环境至少还要考虑:
- 参数外置化和标定,不能把每一台电源的参数都写死在源码里。
- 看门狗和故障自恢复,数字控制卡死时要安全关断。
- 固件升级和版本回滚。
- 过压、过流、过温等硬保护与软件保护配合。
- 采样增益校准,抵消 ADC、运放和电阻误差。
- 电磁兼容设计,数字控制算法要配合 EMI 软件扩展频谱。
- 运行日志和远程监控接口。
学习环境只需要让功能可控,生产环境需要让故障可追溯、参数可维护、版本可回滚。
8. 可复用的数字控制算法检查清单与下一步
8.1 算法落地检查清单
以下几项可以直接作为项目审查清单使用:
- ADC 采样时刻是否避开开关噪声窗口。
- ADC 原始值是否经过标定换算成实际电压电流。
- 控制周期是否固定,并由硬件定时器或 PWM 触发。
- 控制中断里是否存在打印、延时、动态内存分配。
- 输出限幅是否考虑了最小脉宽和最大占空比。
- 积分是否做了条件积分或限幅。
- 软启动是否独立于 PID 控制。
- 故障状态是否记录详细现场信息。
- PWM 极性和死区是否经过开环验证。
- 控制参数是否支持运行时调试和版本管理。
8.2 下一步:从 PID 走向现代控制
传统 PID 在大多数电源场景里已经能解决问题,但负载动态更复杂时,可以研究前馈控制、状态反馈、模型预测控制和自适应控制。比如输入电压前馈可以大幅减小输入跳变带来的输出波动;负载电流前馈可以改善阶跃响应;双向电源还需要增加功率方向判断和模式切换逻辑。
数字电源的核心竞争力并不在某一套控制算法,而在于整个控制逻辑能够在固定周期内稳定、准确、可维护地执行。先把采样、状态机、PI 和故障链路跑稳定,再逐步加入更高级的算法,是更稳妥的路线。