PFC软件代码分析
CCS 开发环境配置
PFC 软件控制与 CCS 开发环境配置
在进行 PFC (功率因数校正) 的数字控制开发时,通常使用德州仪器 (TI) 官方提供的集成开发环境 Code Composer Studio (CCS)。本章将详细介绍 CCS 的基础功能、项目创建、库文件配置以及极其关键的安全调试规范。
CCS 基础操作与功能界面
在使用 CCS 软件时,必须严格遵守一个前提:软件的安装路径以及项目文件夹的路径中绝对不能包含任何中文字符,否则会导致各类未知的编译错误。
如果要导入已有的项目,可以通过菜单栏依次点击 Project -> Import CCS Projects 来完成。例如,本次 PFC 的项目名称为 Demo-PFC-CloseLoop。在 TI 的 C2000 系列开发中,我们通常会大量依赖官方提供的底层库文件,其中最核心的两个文件夹是 DSP2803x_common 和 DSP2803x_headers。
结合 CCS 的功能界面,几个最常用的核心操作如下:
- 编译程序:点击工具栏中类似“锤子”的图标即可进行项目编译。如果代码有语法错误,对应的文件图标上会出现红色的“❌”号,进入文件后具体的报错行也会有红叉提示。
- 烧录/进入 Debug:点击带有绿色“小爬虫”的图标,即可将编译好的程序下载烧录到 DSP 芯片中,并进入仿真调试模式。
- 程序运行控制:在 Debug 模式下,可以使用“运行(绿色播放键)”和“退出 Debug(红色方形停止键)”按钮来控制程序的启停。
- 复位按钮:点击复位按钮,可以将程序指针强制跳转回代码的最开始处(通常是 main 函数入口)重新执行。
- 变量观察窗口 (Variables):在调试过程中,可以将代码中的变量名称拖拽或复制到
Variables窗口中,以实时观察其具体的数值变化。
⚠️ 极其重要的硬件调试安全警告:
在对开关电源进行在线仿真调试时,如果主功率电路已经接入了交流强电,绝对不允许在 CCS 中执行“暂停 -> 继续 -> 暂停”这样的断点或挂起操作!原因分析:开关电源在正常工作时,程序是连续高速运行并不断更新占空比的。如果在调试时突然点击“暂停”,DSP 核心会停止执行代码,但其底层的 PWM 硬件外设可能会保持在暂停瞬间的状态(例如,某个 MOS 管的驱动信号恰好停留在高电平)。这会导致 MOS 管持续导通,母线瞬间直通短路,从而直接炸毁整个电源。
正确做法:在线调试或运行程序时,绝不能加主交流电;必须拔下控制板,在弱电环境下验证控制逻辑无误后,再脱机上强电运行。
新建项目与 C 文件生成
如果是从零开始搭建工程,需要新建 CCS 项目和源码文件。
- 新建工程:选择新建 CCS Project。在弹出的配置窗口中,首先需要在
Target栏选择对应的芯片型号(例如TMS320F28034)。 - 配置烧录器:在
Connection栏选择实际使用的仿真器型号,例如Texas Instruments XDS100v2 USB Debug Probe。 - 命名与模板:在
Project name中输入项目名称(如text),并在下方的项目模板和示例中选择Empty Project (with main.c),这样系统会自动为你创建一个包含 main 函数的空项目。
- 新建 C 文件:如果需要额外添加模块化的 C 语言源文件,可以在项目管理器中右键(或点击菜单栏 File -> New),依次选择
New -> Source File即可建立新的代码文件。
库文件路径识别与 CMD 冲突解决
在新建工程并将 DSP2803x_common 和 DSP2803x_headers 这两个官方库文件夹复制进项目后,直接点击编译通常会引发大量报错。
如图所示,控制台(Console)和问题窗口(Problems)会提示大量 gmake 错误(如 22 errors),这通常是因为编译器无法找到头文件或全局变量定义。原因是新的工程不能自动识别我们导入的库文件路径。
解决方法如下:
- 添加头文件搜索路径:
右键点击工程名称,依次进入Properties -> Build -> C2000 Compiler -> Include Options。
在Add dir to #include search path (--include_path, -I)列表中,先删除原有不相关的默认路径,然后点击添加(Add)按钮,选择Workspace...,从你的项目目录中,分别将DSP2803x_common和DSP2803x_headers文件夹下的include文件夹添加进去。 - 处理 CMD 链接文件冲突:
DSP 的编译需要.cmd文件来分配内存(RAM 或 Flash)。默认新建项目时,根目录下可能会自动生成一个28034_RAM_lnk.cmd文件。
但是,在我们导入的DSP2803x_common/cmd文件夹下,已经包含了官方写好的 cmd 文件。如果项目中同时存在两个 cmd 文件,链接器会报错。- 首先,删除项目根目录下的
28034_RAM_lnk.cmd。 - 其次,展开
DSP2803x_common/cmd文件夹,你会发现里面有两个文件:28034_RAM_lnk.cmd(代表程序在 RAM 中运行调试)和F28034.cmd(代表程序烧录固化到 Flash 中)。一般实际应用中我们使用存入 Flash 的方式。 - 因此,需要选中
DSP2803x_common/cmd文件夹下的28034_RAM_lnk.cmd,右键选择Exclude from Build(从编译中排除),仅保留F28034.cmd参与编译。
- 首先,删除项目根目录下的
TI 官方源码下载渠道
如果你需要获取更全面、底层的头文件、外设驱动代码或官方例程,可以直接从德州仪器 (TI) 的官网获取。
TI 将这些资源打包在一个名为 controlSUITE 的综合套件中。你可以在 TI 官网直接搜索 control suite,下载其离线安装包 CONTROLSUITE-ZIP-Offline(ZIP)Installer,安装后即可在本地浏览所有 C2000 系列的源代码。
PFC端口配置与代码架构
PFC端口配置与代码架构
PFC硬件框架与端口配置
基于 TMS320F28034 控制的 BOOST PFC 整体硬件框架及其信号连接如下图所示。
上图详细标出了 PFC 控制器与 PFC 主功率电路,以及与 LLC 信息交互辅助电路的信号连接定义。对应的控制板上 TMS320F28034 控制器的端口复用功能说明如下表所示:
| 信号名称 | 内容定义 | 控制板信号 | 说明 |
|---|---|---|---|
| ADC_IMOS | MOS电流信号 | ADCINA0 | ADCA0通道 |
| ADC_ACL | 输入L线对PGND电压信号 | ADCINA1 | ADCA1通道 |
| ADC_ACN | 输入N线对PGND电压信号 | ADCINB1 | ADCB1通道 |
| ADC_BUS | 直流母线电压信号 | ADCINB0 | ADCB0通道 |
| PWM1A_DRI | MOS驱动PWM信号 | PWM1A | ePWM模块1A通道 |
| Relay | 继电器控制信号 | GPIO32 | GPIO32口 |
| P_SCI_RXD | SCI通信接收信号 | SCIARXD | SCIA通信接收口 |
| P_SCI_TXD | SCI通信发送信号 | SCIATXD | SCIA通信发送口 |
| PFC_OK_S | PFC状态IO口信号 | GPIO22 | GPIO22口 |
PFC软件架构与中断机制
在数字电源控制中,最好的源代码架构是定时的架构,即在某个固定的时间点触发相应的事件,程序进入处理,处理完毕后立刻退出来,而不是在主程序中一直死循环等待。这种架构能够极大地避免阻塞,从而更高效地利用 DSP 的时间资源。
为简化系统软件架构并增加软件系统的可移植性,本系统正是以这种中断事件触发的思想来设计整体 PFC 软件系统的。
- 初始化与主循环:PFC 控制器在上电或复位后,首先初始化 DSP 的所有外设,打开各组模块功能所需的中断,随后程序进入空循环(空循环中无任何实质性处理)。
- 中断触发运行:软件的主体分别由四个中断内容构成,分别为 ADC 中断、1kHz 中断(1ms定时)、200Hz 中断(5ms定时)、SCI 中断。
- 中断优先级与嵌套:这四个中断的优先级从高到低依次为:ADC中断 > 1kHz中断 > 200Hz中断 > SCI中断。各个中断在运行过程中均开启了中断嵌套功能,这意味着优先级高的中断可以在任意时刻打断正在执行的低优先级中断,确保最紧急的控制任务(如采样与发波)被优先执行。
工程文件说明与函数架构
为了保证 PFC 软件整体编程遵循规范、简易的原则,系统针对不同的中断分别划分了不同的 C 语言文件,并在其中对应编写了该中断所需的执行函数。
整体工程文件划分
| 文件名 | 说明 |
|---|---|
| main.c | 主函数:初始化配置 |
| InterruptADC.c | ADC中断函数文件:数据获取函数,锁相环设计,前馈环设计,参考电流计算,电流环计算,寄存器更新,DCM电流采样矫正,硬件过流保护设计 |
| InterruptADC.h | ADC中断头文件:宏定义 |
| Interrupt1kHz.c | 1kHz中断函数文件:电压平均值计算,电压环参数变增益,BUS参考电压处理,电压环函数,母线电压限制,UVP函数,AC有效值计算函数,DCM前馈参数计算,电流环便增益,前馈软启,电流参考值软启 |
| Interrupt1kHz.h | 1kHz中断头文件:宏定义 |
| Interrupt200Hz.c | 200Hz中断函数文件:PFC状态机函数,输入电压保护,SCI发送数据 |
| Interrupt200Hz.h | 200Hz头文件:宏定义 |
| SCIcom.c | SCI通信功能函数文件:接收中断,SCI状态处理,发送等 |
| SCIcom.h | SCI通信功能函数头文件:宏定义 |
| Table.h | 运算所需表 |
各文件内部函数功能详细定义
以下是各个源文件中封装的具体函数集合及其功能定义:
main.c 文件函数集合
| 函数名 | 说明 |
|---|---|
| main() | 主函数 |
| SysCtrlInit() | 系统时钟初始化配置 |
| Timer0Init() | 1kHz(1mS中断)定时器初始化配置 |
| Timer1Init() | 200Hz(5mS中断)定时器初始化配置 |
| GPIOInit() | IO口功能配置函数 |
| ePWMInit() | ePWM(MOS驱动)初始化配置 |
| ePWMDebugInit() | ePWM 4A初始化配置,模拟DAC功能 |
| ADCInit() | ADC初始化配置 |
| TZInit() | TZ事件初始化配置,用以实现过流快速封波功能 |
| SCIInit() | SCI通信初始化配置 |
InterruptADC.c 文件函数集合
| 函数名 | 说明 |
|---|---|
| ISR_ADC() | ADC中断函数,每个开关周期采样一次 |
| ADCSample() | ADC数据读取,获取电感电流和输入电压 |
| PhaseLockLoop() | 锁相环函数 |
| FeedCal() | 前馈环计算 |
| IrefCal() | 参考电流计算 |
| CurrentLoop() | 电流环计算,得到所需占空比 |
| RegReflash() | PWM寄存器更新 |
| Icalibrate() | DMC模式电流采样较正 |
| HwOcp() | 硬件过流封波保护 |
Interrupt1kHz.c 文件函数集合
| 函数名 | 说明 |
|---|---|
| ISR_1kHz() | 1毫秒的中断函数 |
| VbusAvgCal() | 输出电压采样求平均计算 |
| VloopKpKiCal() | 电压环变增益函数计算 |
| VrefCal() | BUS参考电压处理 |
| VoltageLoop() | 电压环计算函数 |
| VbusLimit() | 母线电压限制 |
| VbusUVP() | 母线电压欠压保护函数 |
| VIacRmsCal() | 计算AC有效值计算函数 |
| DCMFeedCal() | DCM前馈参数计算 |
| IloopKpKiCal() | 电流环便增益 |
| Feedss() | 前馈占空比软启 |
| Irefss() | 电流参考值软启 |
Interrupt200Hz.c 文件函数集合
| 函数名 | 说明 |
|---|---|
| ISR_200Hz() | 5毫秒定时中断函数 |
| StateM() | PFC状态机函数 |
| StateMInit() | 初始化状态 |
| StateMWait() | 等待状态 |
| StateMRise() | 软启动状态 |
| StateMRun() | 运行状态 |
| StateMErr() | 故障状态 |
| VariableInit() | 所有变量初始化 |
| ResetVILoop() | 电压电流环相关参数复位 |
| ImosOffsetCal() | 电流采样偏置计算 |
| VacCheck() | 输入电压检测与保护 |
| PWMDAC() | 用PWM口模拟DAC输出 |
SCIcom.c 文件函数集合
| 函数名 | 说明 |
|---|---|
| ISR_SCI() | 接收中断 |
| MesRxCmd() | 接收数据转存至接收数据帧数组中 |
| MesStore() | 中断接收数据处理函数,将SCI接收寄存器中的数据保存至ACK数组中,并对数据正确性校验 |
| TxDataRecord() | 将需要发送的数据存储到TxData寄存器中 |
| FrameSent() | S发送一帧数据 |
| FrameBuild() | 构建一帧数据,保存于Frame中 |
| SCI_TX() | 调用SCI发送寄存器发送数据 |
| SciCom() | SCI内部通信主函数-主要执行发送操作 |
| SCIValueInit() | SCI相关变量初始化 |
PFC初始化(中断向量初始化)
PFC初始化-中断向量初始化
下面是 PFC 硬件配置、软件架构,DSP 中断分配表以及 main.c 核心代码进行从零开始的逐句拆解。
在高频数字电源控制中,我们需要极其严格的离散时间执行一致性。因此,最合理的源代码架构是基于定时中断的事件触发架构。程序在发生中断时进入处理(如采样、计算控制律、更新占空比),处理完毕后立刻退出,绝不在主程序中死循环等待。
四个主要中断的优先级从高到低依次为:ADC中断 > 1kHz中断 > 200Hz中断 > SCI中断。开启中断嵌套后,高优先级的采样与发波任务随时可以打断低优先级的通信或状态机任务,保证控制系统的实时性。
本项目 PIE 中断机制与向量分配表
TI 28x DSP 的外设中断扩展(PIE)模块像是一个“前台秘书”,负责将多达 96 个外设中断源分组并转交给 CPU。
一个中断信号想要最终到达 CPU 核心,必须经过以下图示中的重重“开关”:
- 外设级别(如 ADC 转换完成标志)
- PIE 级别通道开关 (
PIEIERx) - CPU 级别组别开关 (
IER) - 全局总开关 (
INTM)
根据官方数据手册截图,提取出代码中实际用到(标黄)的中断通道,整理如下表:
| 中断名称 | CPU 组别 | PIE 内部通道 | 触发源说明 | 代码中的向量定义 |
|---|---|---|---|---|
| ADCINT1 | INT1 | INT1.1 (最高优先级) | ADC 模块转换完成触发 | PieVectTable.ADCINT1 |
| TINT0 | INT1 | INT1.7 | CPU 定时器 0 触发 (1ms) | PieVectTable.TINT0 |
| SCIRXINTA | INT9 | INT9.1 | 串口 SCI-A 接收到数据触发 | PieVectTable.SCIRXINTA |
| CPU-Timer1 | INT13 | 直连 CPU (不经过 PIE) | CPU 定时器 1 触发 (5ms) | PieVectTable.TINT1 |
main.c 主程序全代码逐段精解
main.c 是整个系统的“总指挥部”。在执行高频数字控制律之前,总指挥必须先把所有的硬件外设(PWM死区、ADC采样通道、通信接口)全部配置妥当。以下为你将这篇代码拆解为 6 个核心步骤。
关门闭户,准备系统级初始化
1 | int main(void) |
DINT;:结合上面的中断总图,这句指令相当于直接拉下图中最右侧的INTM总闸,屏蔽一切外部中断请求,确保配置硬件时不被打断。DisableDog();:看门狗是一个硬件计时器,程序如果跑飞不喂狗,它就会强制重启 DSP。因为初始化过程较长,为了防止被误判为死机,我们先将其关闭。SysCtrlInit();:这是一个底层封装函数,主要用来配置 DSP 的“心脏”——锁相环倍频(将外部晶振倍频到系统主频),并开启需要用到的外设时钟。- 中断向量表初始化:清空旧的中断跳转“电话簿”,为下一步重新分配做准备。
映射中断服务函数(修改“电话簿”)
1 | EALLOW; |
EALLOW与EDIS:DSP 内部有很多极其危险的受保护寄存器(比如决定中断往哪跳的寄存器)。平时它们是硬件锁死的,必须先用EALLOW(解除保护)才能修改,改完马上用EDIS重新锁死。&ISR_ADC等:利用 C 语言的取址符,告诉硬件:“当ADCINT1发生时,程序指针强制跳转到名为ISR_ADC的函数去执行”。
突破速度瓶颈(代码搬移至 RAM)
1 | memcpy((Uint16 *)&RamfuncsRunStart, (Uint16 *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize); |
- 核心意义:由于 Flash(固态存储)读取速度极慢,每次读取代码都会产生等待周期(Wait States),这会导致数字电源控制环路出现严重的执行抖动(Jitter)。通过 C 标准库函数
memcpy,在开机瞬间将对时间极其敏感的核心控制代码从 Flash 复制到高速 RAM 中运行,彻底消除计算延迟。
逐个激活外设模块
1 | Timer0Init(); // CPU TIMER0 初始化 1ms(1Khz) |
- 这里调用的是自定义的子函数,分别去设置具体的控制参数(例如在
ePWMInit中写入控制母线电压的 PWM 互补发波逻辑和死区时间)。
逐层打通中断链路
1 | EALLOW; |
- 结合上面新增的 中断总图 来看:
PIEIERx配置的就是图中下半部分的PIEIERx(8:1)开关。IER配置的是图中上半部分的IER(12:1)开关。EINT配置的是最右侧连接到 CPU 的INTM那个总开关。
- 中断就像水流,必须同时打开分支阀门 (PIEIER)、主管道阀门 (IER) 和 总水闸 (EINT),中断信号才能最终传达到 CPU 核心。
最终启停同步与主循环
1 | DELAY_US(5000); // 延时 5ms,等待所有电路与时钟彻底稳定 |
TBCLKSYNC = 1:这对于电源控制极为重要。它能确保芯片内多个独立的 PWM 模块时钟计数器在同一瞬间同时起跑,彻底避免发波相位的错乱。执行到这里,
main所有的准备工作均已结束。随后系统会完全依靠定时器和 ADC 的节拍,自动在各个中断之间有序跳转,执行精确的母线闭环控制。下面是这部分的完整代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* main.c
*/
//系统时钟配置初始化
void SysCtrlInit(void);
//定时器0配置初始化 1kHz中断
void Timer0Init(void);
//定时器1配置初始化 200Hz中断
void Timer1Init(void);
//IO口功能配置函数
void GPIOInit(void);
//ePWM1初始化函数
void ePWMInit(void);
//ADC 初始化函数
void ADCInit(void);
//硬件过流,硬件过压TZ封波初始化函数
void TZInit(void) ;
//SCI通信初始化
void SCIInit(void);
//ePWM初始化函数(调试用)
void ePWMDebugInit(void);
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;
int main(void)
{
DINT;//关闭所有中断
DisableDog(); //关看门狗
SysCtrlInit(); //初始化系统功能
InitPieCtrl();//复位中断向量
InitPieVectTable();//初始化中断向量表
EALLOW;
PieVectTable.ADCINT1 = &ISR_ADC;//ADC中断定义
PieVectTable.TINT0 = &ISR_1kHz;//1kHz中断名定义
PieVectTable.TINT1 = &ISR_200Hz;//200Hz中断名定义
PieVectTable.SCIRXINTA=&ISR_SCI;//SCI接收中断
EDIS;
memcpy((Uint16 *)&RamfuncsRunStart,(Uint16 *)&RamfuncsLoadStart,(unsigned long)&RamfuncsLoadSize);
InitFlash();
Timer0Init();// CPU TIMER0 初始化 1ms(1Khz)
Timer1Init(); // CPU TIMER1 初始化 5ms(200hz)
ePWMInit();//ePWM1/初始化函数
TZInit();//比较器1初始化
ePWMDebugInit();//ePWM4初始化函数(调试用)
GPIOInit();//GPIO口初始化
SCIInit();//SCI初始化
ADCInit();//ADC采样初始化
EALLOW;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; //Timer0 使能
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //ADC中断1使能
PieCtrlRegs.PIEIER9.bit.INTx1 = 1; // SCI中断使能;
EDIS;
PieCtrlRegs.PIEACK.all = 0xFFFF;
IER = M_INT1|M_INT9|M_INT13; // 开中断INT1/ INT13
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
DELAY_US(5000);//延时
CpuTimer0Regs.TCR.bit.TSS = 0; // Timer0使能;
CpuTimer1Regs.TCR.bit.TSS = 0; // Timer1使能;
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // enable TBCLK within the ePWM
EDIS;
PFC初始化(时钟与定时器初始化)
PFC初始化(时钟与定时器初始化)
本章的核心任务是为 PFC(功率因数校正)数字控制系统配置极其稳定的“心跳”(系统时钟),以及一个绝对准时的“闹钟”(定时器)。由于我们的核心目标是控制公共直流母线电压的稳定,这些底层时钟的精确度直接决定了电压环和电流环算法的执行精度。
在解析代码之前,我们首先依据官方数据手册,将代码中用到的所有底层硬件寄存器进行表格化汇总。
系统时钟控制 (CLKCTL) 寄存器全映射表
代码中对 SysCtrlRegs.CLKCTL 进行了十余项配置。以下汇总表将代码中的每一行设定,与官方手册中高亮的功能说明进行了严密的映射与中文翻译:
| 寄存器与位 (Bit) | 代码设定值 | 手册功能说明 (中文翻译) | 对应代码原句 |
|---|---|---|---|
| Bit 15: NMIRESETSEL | 0 | 无延迟驱动 MCLKRS 复位信号 (低电平有效,复位默认值) | SysCtrlRegs.CLKCTL.bit.NMIRESETSEL = 0; |
| Bit 14: XTALOSCOFF | 1 | 关闭外部晶体振荡器 | SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 1; |
| Bit 13: XCLKINOFF | 1 | 关闭外部时钟输入引脚 (XCLKIN) | SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1; |
| Bit 12: WDHALTI | 0 | 进入暂停 (HALT) 模式时自动关闭看门狗 (复位默认值) | SysCtrlRegs.CLKCTL.bit.WDHALTI = 0; |
| Bit 11: INTOSC2HALTI | 0 | 进入暂停 (HALT) 模式时自动关闭内部振荡器 2 (复位默认值) | SysCtrlRegs.CLKCTL.bit.INTOSC2HALTI = 0; |
| Bit 10: INTOSC2OFF | 1 | 关闭内部振荡器 2 | SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1; |
| Bit 9: INTOSC1HALTI | 0 | 进入暂停 (HALT) 模式时自动关闭内部振荡器 1 (复位默认值) | SysCtrlRegs.CLKCTL.bit.INTOSC1HALTI = 0; |
| Bit 8: INTOSC1OFF | 0 | 开启内部振荡器 1 | SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 0; |
| Bits 7-5: TMR2CLKPRESCALE | 000 (0) | CPU 定时器 2 时钟预分频值 (0代表不分频) | SysCtrlRegs.CLKCTL.bit.TMR2CLKPRESCALE = 0; |
| Bits 4-3: TMR2CLKSRCSEL | 10 (2) | 选择内部振荡器 1 | SysCtrlRegs.CLKCTL.bit.TMR2CLKSRCSEL = 2; |
| Bit 2: WDCLKSRCSEL | 0 | 选择内部振荡器 1 (复位默认值) | SysCtrlRegs.CLKCTL.bit.WDCLKSRCSEL = 0; |
| Bit 1: OSCCLKSRC2SEL | 0 | 选择外部振荡器 (复位默认值) | SysCtrlRegs.CLKCTL.bit.OSCCLKSRC2SEL = 0; |
| Bit 0: OSCCLKSRCSEL | 0 | 选择内部振荡器 1 (复位默认值) | SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 0; |
锁相环 (PLL) 状态与配置寄存器全映射表
为了将 10MHz 的初始时钟安全地倍频至 60MHz,代码严格遵循了硬件倍频的安全规程。以下是相关寄存器的中文映射汇总:
| 寄存器与位 (Bit) | 设定值/操作 | 手册功能说明 (中文翻译) | 对应代码原句 |
|---|---|---|---|
| PLLSTS Bits 8-7: DIVSEL | 0 / 3 | 选择时钟 1 分频 | 先清零:SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;后写3: SysCtrlRegs.PLLSTS.bit.DIVSEL = 3; |
| PLLSTS Bit 6: MCLKOFF | 1 / 0 | 禁用主振荡器故障检测逻辑,且 PLL 不会发出跛行模式 (limp-mode) 时钟。 | 临时关闭:SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;后重启: SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0; |
| PLLSTS Bit 4: MCLKCLR | 1 | 强制清除并复位时钟丢失检测电路。 | SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1; |
| PLLSTS Bit 3: MCLKSTS | 读取判断 | 指示检测到系统时钟 (OSCCLK) 发生丢失。 | if(SysCtrlRegs.PLLSTS.bit.MCLKSTS) |
| PLLSTS Bit 0: PLLLOCKS | 循环死等 | 指示 PLL 已完成频率锁定,当前输出处于稳定状态。 | while(!SysCtrlRegs.PLLSTS.bit.PLLLOCKS); |
| PLLCR 组合设定 | DIV=6 | 表格交叉项:0110 (对应十进制6) 结合 PLLSTS[DIVSEL] = 3,输出公式为 (OSCCLK * 6)/1 | SysCtrlRegs.PLLCR.bit.DIV = 6; |
系统时钟初始化代码逐句精解 (SysCtrlInit)
结合上述两张翻译后的映射表,我们可以清晰地看出 SysCtrlInit 底层硬件配置的逻辑全貌:
1 |
|
1 | void SysCtrlInit(void) |
定时器0 初始化与算法原理解析 (Timer0Init)
我们需要 Timer0 产生一个精确的 1kHz(1ms)的定时中断。这个定时器决定了母线电压环的运算节拍。
1 | * 函 数:void Timer0Init(void) |
1 | void Timer0Init(void) |
定时器1 初始化与算法原理解析 (Timer1Init)
我们需要 Timer1 产生一个精确的 200Hz(5ms)的定时中断。
1 | * 函 数:void Timer1Init(void) |
1 | void Timer1Init(void) |
底层硬件差异:中断寄存器路由图解
结合《CPU-Timer 中断信号与输出信号》路由图,我们可以彻底弄懂为什么 Timer0 和 Timer1 在中断配置时有着本质区别。
- 常规路径(CPU-TIMER 0):
观察图表的最上方:CPU-TIMER 0溢出产生的信号名叫TINT0。顺着向左的箭头看去,这个信号必须先经过一个名为 PIE(外设中断扩展)的中间模块,才能最终变为INT1信号抵达 28x CPU。 - 对应代码体现:正因为如此,凡是使用 Timer0 计算控制环路,在
main()主函数里就必须显式地去配置PIEIER寄存器(相当于手动让 PIE 秘书放行)。
- 直达专线(CPU-TIMER 1 和 2):
观察图表的下方:CPU-TIMER 1和CPU-TIMER 2产生的信号叫TINT1和TINT2。这两条线直接绕过了 PIE 模块,作为高级别的专线,直接连到了 28x CPU 的INT13和INT14引脚上。 - 对应代码体现:所以,在使用 Timer1 的代码配置中,您绝对找不到任何关于 PIE 寄存器的操作,因为它有直达 CPU 的特权,只需打开 CPU 主管道(
IER |= M_INT13)即可被立刻响应。
PFC初始化(普通 IO 口与 PWM 模块配置)
PFC初始化:普通 IO 口与 PWM 模块配置
在 PFC(功率因数校正)控制系统中,DSP 需要两种“手”来控制外部电路:
- 慢速的手(普通 IO 口): 负责开关继电器、点亮 LED 指示灯、输出简单的状态信号。
- 快速且精准的手(PWM 模块): 负责以几万赫兹的频率高频驱动开关管,并精准踩点触发 ADC 采样,这是维持母线电压稳定的核心。
普通 IO 口初始化 (GPIOInit)
普通 IO(General-Purpose Input/Output)也就是通用引脚。在配置一个引脚之前,DSP 默认它是断开或随机状态的。我们需要明确告诉芯片:这个引脚是做普通开关用,还是做特殊通信用?是负责输出电压,还是负责读取电压?
端口分配与设计要求
根据系统硬件设计,我们需要用到以下普通 IO 口:
- 清理现场: 初始化前,清除 GPIOA(引脚0-31)和 GPIOB(引脚32-63)的所有历史状态,防止误动作。
- GPIO32: 配置为输出,用于控制继电器的吸合与断开。
- GPIO22: 配置为输出,用于向外发送
PFC-OK状态信号。 - GPIO23: 配置为输出,用于驱动控制板上的状态指示 LED 灯。
- GPIO24 / GPIO33: 配置为输出,预留给后续的开发与调试使用。
代码逐句精解
1 | void GPIOInit(void) |
⚙️ 运行逻辑小结:
配置 IO 口通常只需两步:先设定 MUX 决定它的身份(普通脚还是外设脚),再设定 DIR 决定它的方向(输入还是输出)。
核心 PWM 模块初始化 (ePWMInit)
为了将母线电压稳稳地控制在目标值,PFC 使用了单周期控制法。这意味着在极其短暂的一个 PWM 开关周期内,DSP 必须完成一次“电流采样 -> 环路计算 -> 更新占空比”的完整闭环。
PWM 发波与 ADC 采样的时序配合
我们采用的是平均电流控制模式。从物理规律上讲,在一个三角载波周期中,电感电流在三角波的顶点处刚好等于这段时间的平均电流。因此,我们必须精准地在三角波的顶点触发 ADC 采样。
硬件配置参数计算:
- 系统主时钟: 60MHz。
- 目标 PWM 频率: 45kHz。
- 发波模式: 上升下降模式(先往上数,再往下数,形成等腰三角形)。
- 周期寄存器 (
TBPRD) 值:
由于是上下数数,相当于走了一个来回,所以要除以 2。
当计数器从 0 数到 667,再从 667 数回 0,刚好耗时 $\frac{1}{45\text{k}}$ 秒。
ePWM的功能有下面的功能
功能1:TB功能,时钟功能和计时功能也就是产生载波的功能
功能2:CC功能,也就是比较器的功能,也就是COMPA
功能3:AQ功能,计时达到COMPA的时候PWM是下降还是上升
功能4:DB功能,死区,在PWMA和PWMB两路中要有死区,但是我们这里只用了一路,就不需要死区
功能5:TZ功能,快速触发信号,快速触发PWM进行过流保护的
功能6:ET功能,事件功能,在载波的最高点产生一个事件,我们用这个事件触发ADC采样
为什么要有“镜像寄存器 (Shadow Register)”?
代码中多次出现了 SHADOW(镜像/影子)字眼。
- 问题: 如果 DSP 正在发波的过程中,控制算法突然算出了一个新的占空比并直接写入,波形就会瞬间产生畸变,这可能导致母线电压炸机。
- 解决: 引入“缓冲区”(镜像寄存器)。算法算出的新数据先放在缓冲区排队。等到当前这个周期彻底结束(比如计数器归 0 时),硬件才会自动把新数据放进去。这保证了波形的绝对平滑。
代码逐句精解
1 | /***************************************************************************** |
1 |
|
调试用高频 PWM 初始化 (ePWMDebugInit)
在开发过程中,我们需要实时观察 DSP 内部的某些变量(比如数字环路计算出的母线电压参考值)。但 DSP 内部全是数字信号,用示波器看不到。
解决办法(DAC 模拟技术):
利用 ePWM4 模块输出一个高达 200kHz 的高频 PWM 波。通过改变这个高频波的占空比,再经过外部硬件电路上焊接的两级 RC 低通滤波器,就能把它“平滑”成一个模拟电压信号。我们用示波器量这个模拟电压,就能反推 DSP 内部的变量状态。
代码逐句精解
1 | /***************************************************************************** |
1 | void ePWMDebugInit(void) |
PFC初始化(ADC模块精解)
PFC初始化:ADC (模数转换) 模块精解
对于初学者来说,ADC(Analog-to-Digital Converter,模数转换器)的配置往往看起来最复杂,因为它涉及到很多内部的“开关”和“通道”。但别担心,我们结合提供的结构图和时序图,一步步把它的底层逻辑拆解清楚。
在我们的 PFC 控制系统中,无论是控制母线电压,还是限制电感电流,DSP 都必须先“看”到这些真实的物理量。ADC 的作用,就是把电路中真实的模拟电压信号,转换成 DSP 能看懂的数字。
预备知识:理解 SOC 与“同时采样”机制
结合提供的内部架构图,我们需要先弄懂两个核心概念:
1. 什么是 SOC (Start of Conversion)?
SOC 可以理解为去银行办业务的“排队叫号系统”。
DSP 内部有 SOC0 到 SOC15 共 16 个“号码牌”。在代码中,我们通过控制这 16 个号码牌来决定采样的顺序。比如,我们规定 SOC0 拥有最高优先级,并且把 SOC0 绑定到通道 ADCINA2,那么当触发信号到来时,ADC 就会优先去采集 A2 通道的电压。
2. 什么是“同时采样 (Simultaneous Mode)”?
观察图中间的部分,你会发现输入电路(Input Circuit)分为上、下两半,分别有两个采样保持器(S/H-A 和 S/H-B)。
- 这意味着 DSP 可以在同一微秒内,同时给两个通道“拍快照”。
- 在代码中,如果开启了同时采样,SOC0 和 SOC1 就会自动结对。只要触发 SOC0,硬件就会同时采集 A0 和 B0;触发 SOC2,就会同时采集 A1 和 B1。这对于需要严格时间同步的电压和电流环路计算极其重要。
核心控制流:PWM、ADC与中断的完美配合
控制代码并不是一直在死循环里计算的,它必须严格踩着节拍运行。请仔细提供的时序图,它揭示了整个系统最核心的心跳节奏:配合 EPWM1 模块触发 ADC 采样,并在采样完成后触发采样中断,以此来对采样数据进行处理。
- 触发点: 当 PWM 计数器达到顶点(TBPRD = 667)时,代表此时的电感电流恰好等于平均电流,此时 EPWM1 发出一个触发信号。
- ADC 采样: ADC 收到触发信号后,立刻开始采样并转换。
- 触发中断: 当 ADC 转换完成,把数据存入结果寄存器后,立刻向 CPU 申请中断(即图中的 ADC中断)。
- 算法计算: CPU 暂停手头工作,进入中断服务函数,拿刚刚采到的最新电压电流数据,计算出下一步需要的新 PWM 占空比。
- 占空比生效: 算出的新占空比先放在镜像寄存器(缓冲区)里,等到 PWM 计数器落到谷底(0)时,新占空比正式更新生效,迎接下一个周期的到来。
ADC 初始化代码逐句精解 (ADCInit)
结合文档说明,我们将代码块拆解并详细解释其配置逻辑:
基础环境与时钟配置
1 | void ADCInit(void) |
配置“叫号系统”的优先级与采样模式
1 | // SOC0-1 / SOC2-3 同时采样 |
通道绑定与触发源选择 (核心步骤)
这里是代码和硬件电路直接对话的地方。我们要告诉 SOC 号码牌对应去读取哪个物理引脚的电压。
1 | // SOC0 对应 ADCINTA0(电感电流) |
中断配置 (让 ADC 采样完去叫醒 CPU)
采完数据必须及时处理,否则毫无意义。
1 | // 当采样数值保存至 Result 寄存器后触发中断 |
ADC 内部电路上电
ADC 是一个精密的模拟电路,包含了运放、基准源等,需要给这些物理部件接通电源。
1 | // ADC 模拟电路内部核模块上电 |
通过这一章的配置,系统不仅明确了“什么时候采”、“采哪条线的电压”,而且打通了从 PWM 发波到 ADC 采样,再到 CPU 中断算法计算的完整数据通路。
PFC初始化(过流保护和SCI初始化)
PFC初始化-过流保护和SCI初始化
在开发数字电源控制系统(特别是用于稳压公共直流母线的 PFC 级)时,除了常规的电压电流双闭环控制,系统底层的安全响应机制和级联设备的通信连接是必不可少的两环。
这一章,我们将按照工程逻辑,为你详细拆解这两个独立且重要的硬件模块:
- 硬件过流保护 (TZ 模块):这相当于给你的功率开关管上了一份“硬件级”的物理保险,由于它不需要 CPU 介入计算,其反应速度远超代码算法。
- 串口通信 (SCI 模块):PFC 作为前级电源,需要与后级的 LLC 变换器交流信息(比如交互母线电压的状态或故障码),SCI 就是它们之间的“对讲机”。
硬件过流保护与比较器初始化 (TZInit)
为什么有了算法保护,还需要 TZ (Trip Zone) 保护?
在软件算法控制中,如果系统通过 ADC 采样 $\rightarrow$ CPU 计算闭环 $\rightarrow$ 发现严重过流 $\rightarrow$ 关断 PWM,这个全过程最快也需要几个微秒。但在实际的高频母线电压控制中,如果负载侧瞬间短路,MOS 管在一微秒内就会因瞬间大电流而炸毁。
因此,DSP 硬件架构中提供了一种纯硬件的物理保护机制——Trip Zone (TZ)。PFC 控制具有电流硬件过流快速关闭 PWM 的功能。它完全绕过了 CPU 的代码逻辑,在底层直接将电流传感器的模拟信号与我们设定的危险阈值进行比较,一旦超标,通过事件触发 TZ 模块直接关闭 PWM。
保护电路信号流向分析
我们结合原理图来理解这个物理连线过程:
- 捕捉 MOS 电流:外围硬件采样电阻测到的 MOS 电流信号,在经过一级简单的 RC 低通滤波电路后,被直接送入了 DSP 内部比较器的正端 (+) 输入端口。
- 划定危险红线 (DAC 参考值):我们在代码中利用 DSP 内部集成的 DAC(数模转换)模块,生成了一个固定的模拟基准电压,将其送入比较器的负端 (-)。
- 硬件触发锁死:MOS 电流与内置 DAC 产生的基准电压进行实时的模拟比较。当代表真实电流的电压转换量大于设定的 DAC 基准电压时,比较器输出发生硬件翻转。这个翻转信号经过反向后,产生 TZ 事件信号(即图中拉低的负脉冲
TZ1)。
- 切断输出:PWM 模块的硬件机制检测到
TZ1收到负脉冲,就会立刻强制触发 PWM 输出关闭,从而瞬间保护开关管免受损害。
代码逐句精解
1 | void TZInit(void) |
串口通信初始化 (SCIInit)
PFC 作为整个系统的前端功率校正级,承担着控制母线电压的任务。但在实际的高级电源架构中,PFC 的 SCI 通信功能主要用于实现与后级 LLC 模块相互进行信息交流。
串口通信波特率底层的计算数学
要保证两个芯片通过 TX/RX 顺利通讯,它们的编解码速率(Baud Rate,波特率)必须严丝合缝。你的代码中将 SCI 通信速率配置为 4800 bit/s。
在 TI DSP 中,波特率是通过内部的时钟预分频电路产生的,其数学推导公式如下:
已知我们设定的系统低速外设时钟频率 (LOSPCP) 同样跑在系统主频的 $60\text{MHz}$,将目标波特率 4800 代入公式,反推核心的分频寄存器值 ($\text{BRR}$):
把十进制的 390 转换为十六进制整数,刚好等于 0x0186。这就是代码注释中公式的来源,也是我们要在代码中填入 SCIHBAUD 和 SCILBAUD 寄存器的数字。
代码逐句精解
1 | void SCIInit(void) |
ADC数据采集与数字量标幺化转换
ADC数据采集与数字量标幺化转换
在数字电源控制系统中,DSP 芯片无法直接“理解”外围的模拟电压和电流。必须通过硬件分压、运放调理后,交由 ADC(模数转换器)读取,最后通过严谨的定点数数学运算,才能转化为控制算法可用的数字量。本章将详细拆解这一从“模拟硬件”到“数字代码”的完整转换链路。
基础概念:定点数(Q格式)与系统参数定义
在数字控制中,为了避免极其消耗 CPU 资源的浮点数除法运算,我们通常采用定点数(Q格式)进行标幺化处理。DSP 中尽量不要用除法,而是利用移位操作:向左移位相当于乘法(如左移三位相当于 $\times 8$),向右移位相当于除法。
常规数字量定义:
内部运算中定义了以下 Q 格式基准:
$Q10 = 2^{10}$,$Q12 = 2^{12}$,$Q13 = 2^{13}$,$Q14 = 2^{14}$,$Q15 = 2^{15}$,$Q16 = 2^{16}$
在本 PFC 系统中,统一采用 Q15 格式作为运算标准,即内部数字 $32768$ 代表 ADC 的最大满量程(对应 DSP 引脚输入电压 $3.3\text{V}$)。
PFC工作整体参数定义:
- 交流输入最低,额定,最高有效值:
$V_{acmin} = 187\text{V}$
$V_{acnom} = 220\text{V}$
$V_{acmax} = 253\text{V}$ - 定义 PFC 工作开关频率为:
$f_s = 45\text{kHz}$ - PFC 电感为:
$L_{PFC} = 1.5\text{mH}$ - 电网最小,额定,最大频率:
$f_{lmin} = 45\text{Hz}$
$f_{lnom} = 50\text{Hz}$
$f_{lmax} = 70\text{Hz}$ - 额定母线电压(本系统致力于稳定公共直流母线电压):
$V_{bus} = 380\text{V}$
ADC 中断整体控制流
每个开关周期采样后会有一个 ADC 采样中断。ADC 中断在 SOC3 数据采集完且装载寄存器后触发,拥有最高的中断优先级(优先级 0,快速中断)。
正如上图的流程所示,ADC 中断函数是整个控制系统的心跳,内部包含了从采样到闭环计算再到更新发波的全过程。
1 | //采样变量结构体 |
硬件转换逻辑与 ADC 采样函数解析
ADCSample() 函数的主要任务是从 ADC 结果寄存器中提取原始机器码,统一转换为 Q15 格式的数据,并转存至指定的结构体变量中。为了彻底理解代码中的比例关系,我们需要结合硬件原理图进行数学推导。
交流电网电压与母线电压采样
1. 交流电网电压采样硬件与公式推导
对于交流电网,VacL 是火线,VacN 是零线。由于是交流电,我们需要分别对火线和零线进行独立采样,而后在软件中做差分计算。
根据电路原理图定义,数据交流电压采样电阻分别为:
$RA_{30} = 243\text{k}\Omega$
$RA_{31} = 243\text{k}\Omega$
$RA_{33} = 3.3\text{k}\Omega$
DSP 能够采样到的最高 ADC 口电压为:
$V_{dsp} = 3.3\text{V}$
采集的电压是小电阻RA33上的电压
根据分压原理反推出 DSP 能够采样到的输入最高电压为:
定义 Q15 数据为 DSP 最大量程电压数字量(对应 3.3V),则得到输入电压 L 线或者 N 线对应的数字量函数为:
输入电压 占最大可测电压 的比例,就等于 DSP 内部数字量占 Q15 最大量程的比例。
举例说明,输入 L 线或者 N 线对 PGND 的电压为 $220\text{V}$,则对应 DSP 内部的数字量为:
2. 母线电压采样硬件与公式推导
控制核心是稳定直流母线电压,其采样网络结构与交流输入完全一致。
根据电路原理图定义,数据交流电压采样电阻分别为:
$RA_{17} = 243\text{k}\Omega$
$RA_{18} = 243\text{k}\Omega$
$RA_{21} = 3.3\text{k}\Omega$
根据分压原理反推出 DSP 能够采样到的 BUS 最高电压为:
同样,得到母线电压对应的数字量函数为:
举例说明,额定母线电压为 $380\text{V}$,则对应 DSP 内部的数字量为:
MOS 电流采样与硬件偏置
这是最容易踩坑的环节。电流是通过底部的精密检流电阻转化为电压,再经过运放放大的。
设计使用运放的 1 通道构建零偏置电压,定义偏置电路的电阻参数为:
$RA_{20} = 4.7\text{k}\Omega$
$RA_{16} = 1\text{k}\Omega$
计算偏置电压(避免运放零偏)为:
定义 MOS 电流采样电阻与差分放大电路的电阻为:
$RA_{13} = 0.01\Omega$
$RA_{22} = 2.2\text{k}\Omega$
$RA_{23} = 100\Omega$
则差分电流变换的运放增益为:
根据差分变换电路增益,采样电阻,和 DSP 标定电压 3.3V,计算 MOS 电流最大采样值为:
定义 Q15 数据对应的函数为:
举例,当 MOS 电流为 $0.15\text{A}$,对应内部数字量为:$I_{Ldsp}(0.15\text{A}) = 327.68$
数据转换代码实现 (ADCSample)
结合上面的硬件推导,我们再来看代码就会一目了然:
1 | /* |
通过这一套完整的“采集 $\rightarrow$ 格式扩位 $\rightarrow$ 扣除硬件偏置 $\rightarrow$ 模式矫正”流程,DSP 终于在内存中还原出了高精度的真实物理世界波形,为后续的数字环路运算打下了坚实基础。
PFC锁相环代码分析
PFC锁相环代码分析
在PFC(功率因数校正)控制中,如果直接使用ADC采样的电网电压作为参考,电网中的噪声、谐波和突变都会导致控制系统发散。
因此,软件锁相环(PLL) 的核心目的在于:通过内部算法,构建出一个与实际输入电网电压同相位、同频率的“完美”标准正弦波信号(峰峰值为1)。用这个纯净的信号构造电流的参考值。
下面我们将把代码、公式推导、定标原理彻底拆解,让你真正看懂每一步为什么这么做。
核心基石:标准化正弦数据表
为了避免在单片机中进行极其消耗CPU算力的浮点正弦函数计算,我们在程序中提前写死了一张包含 1024 个点的正弦数据表。这张表代表了完美的半个正弦波。
这张表里的数值是用 Q12格式 存储的。所谓 Q12,就是把真实的小数放大了 $2^{12}$(即 4096)倍。由于正弦波的最大值是 1,所以表中峰值对应 $1 \times 4096 - 1 = 4095$。
1 |
|
查表步长的数学推导与 Q12 定标处理
问题来了:如果一次中断我们查表走 1 格,1024 个中断才能走完半个正弦波。但实际上我们进中断的次数是受开关频率控制的。
我们如何确保在“真正的半个电网周期内”,刚好把这 1024 个点匀速取完?这就是计算步长 (Step) 的核心逻辑。
若正弦表查表时间为 $T_{table_search}$(即我们的开关周期),电网周期时间为 $T_{line}$,则在半个工频周期内,单片机总共会进去查表的次数 $N_{total}$ 为:
其中 $n$ 代表每间隔 $n$ 个开关周期查表一次(在本程序中,每个周期均查表,即 $n=1$),$F_{switch}$ 为开关频率。计算每次查表步长 $Step$(即每次中断要在表中跨越多少个点)的公式为:
以工频 50Hz 为例进行推演:
软件自定义的半正弦表数据为 1024 个,即正弦表长度为:
若锁相环计算频率为 45kHz(开关周期),那么在半个工频周期(0.01秒)内总共可以计算 450 次(45kHz / 100Hz):
这个 0.01秒 是由我们日常使用的交流电标准频率推导出来的,计算过程非常简单。
确定工频频率:
在我国(以及世界上绝大多数国家),标准的市电频率(即工频)是 50Hz。这意味着电网中的交流电每秒钟会完成 50 个完整的正弦波循环。计算一个完整的周期时间:
周期 $T$ 和频率 $f$ 互为倒数,公式为:所以,一个完整的 50Hz 工频周期时间为:
计算半个周期时间:
既然一个完整的周期是 0.02秒,那么提到的半个工频周期自然就是:
💡 补充说明图片中为什么除以 100Hz:
这里的 100Hz 指的是“半周期的频率”。因为 1 秒钟内电网有 50 个完整的周期,也就意味着有 100 个“半周期”(一正一负交替,1秒钟过零 100 次)。
因此,DSP 的开关频率 45000Hz 也就是一秒钟计算 45000 次,平摊到这 100 个半周期里,每次半个周期(0.01秒)内刚好执行 $45000 / 100 = 450$ 次计算。
为了让 450 次计算刚好走完 1024 个数据点,每次从表中取数的步长应当是:
定标的必要性与 Q12 转化:
由于 2.276 是一个带小数的数字,DSP 如果直接做浮点累加会极耗资源且容易丢失精度(因为 $N_{total}$ 值越大,$Step$ 越小,锁相越需要精确)。
因此,我们对其进行 Q12 放大的定标处理,将小数化为大整数:
(注:也就是 $2.276 \times 4096 \approx 9322$)
同时,电网频率并不是绝对稳定在 50Hz 的。由锁相环的工作原理可知,在不同的输入电网频率下对应的锁相环计算步长不一样。由此可以计算出在极限情况下的步长边界:
这就解释了稍后代码中为何会有 >13005 和 <8389 的步长限制保护参数。
这两个公式是为了推导锁相环步长在极端电网频率下的上下限保护值。在实际的工业环境中,电网频率不可能永远完美保持在 50Hz,它可能会因为电网负荷波动而升高或降低。为了防止软件因为误采样或频率突变算出极其离谱的步长导致系统崩溃,需要通过这些公式提前锁定一个允许的最大值和最小值。
逐个拆解公式里这些字母参数的物理和算法含义:
与 :
这就是我们在代码里最终要使用的步长极限保护参数(经过定标放大后的纯整数)。图片中算出其分别对应 $1.305 \times 10^4$ (即 13005) 和 $8.389 \times 10^3$ (即 8389)。$PLL_{num}$:
正弦表的数据长度。在我们的程序中,半个标准正弦波由 1024 个离散点组成,所以这个常数固定为 1024。$f_s$:
系统的开关频率(或中断计算频率)。代表 DSP 一秒钟内能够执行多少次锁相环代码。前面的设定中是 45000(45kHz)。$f_{lmax}$ 与 $f_{lmin}$:
系统允许的输入电网最高与最低极限频率(Line Frequency Max / Min)。- 如果把 $f_{lmax}$ 设为 70Hz 左右代入公式,算出来的步长就是 13005。意味着电网频率再怎么快,我的步子最大也就迈这么大。
- 如果把 $f_{lmin}$ 设为 45Hz 左右代入公式,算出来的步长就是 8389。
$2 \cdot f_{lmax}$ (分母中的乘 2):
为什么电网频率要乘 2?因为交流电的一个完整周期包含“正半周”和“负半周”两个部分。我们代码里用到的 1024 这个表,只代表了“半个波”。所以对应过零检测的频率,自然是实际电网频率的 2 倍。分母整体 :
这一整块代表在极端频率下,半个电网周期内 DSP 到底能触发多少次中断(也就是总共能走多少步)。用总长度 1024 除以这个步数,得到的就是真实的物理步长(带小数)。$Q12$:
定标放大倍数。为了不让 DSP 去算耗时的小数,把前面算出来的带小数的真实步长,统一乘以 $2^{12}$(也就是 4096),放大成整数供代码直接使用。
步长的动态 PI 补偿(自适应频率变化)
如果电网永远是绝对的 50.00Hz,那步长永远是 2.276。但实际电网频率会漂移,如果固定步长,跑完 450 次中断后,我们累加出来的正弦表位置可能不到 1024,或者超过 1024。
为了修正误差,引入了 PI(比例积分)补偿的思想。 每半个工频周期结束(电网发生实际过零)时,我们进行一次“对账”:
- 若 $T > T_{line}$(电网周期变短,频率升高): 真实的硬件电网已经过零了,但我们的锁相环累计还没跑到 1024。这说明原来的
Step太小了,产生了正误差($E_{cnt} > 0$)。此时通过 PI 调节器将步长增大 (step ↑)。 - 若 $T < T_{line}$(电网周期变长,频率降低): 我们的锁相环早就提前跑完 1024 了,结果真实的硬件电网才发生过零。这说明
Step太大了,产生了负误差($E_{cnt} < 0$)。此时通过 PI 调节器将步长减小 (step ↓)。
当电网周期量增大时,环路计算出的步长量增加;反之则减小。这使得锁相环能时刻贴合实际电网。
软件代码实现流程拆解
锁相环函数具体程序流程图如下图所示。函数首先判断输入电压大于零还是小于零,根据输入电压极性进入不同的分支。
过零防抖设计: 当电压大于0时,进入正半周期锁相处理。为消除误采样或电网畸变引起的过零误判断,程序必须判断前半周期的计数值(大于100)。这就意味着如果刚过零又马上因为噪声跳回负数,程序不会被骗。
如果在周期末尾(真正的过零瞬间),程序会计算上一周期的锁相环误差(1023 - 当前指针)。若误差大于零,增加步长;若误差小于零,减小步长。正半周期与负半周期代码完全对称。当在负半周期计数值达到100时,说明波形稳定,有效值计算标志位将被置1。
结合上面的逻辑,代码逐行解析如下:
1 | /* |
❓ 核心疑问:直接输出 PLL.CntFianl 这个整数作为参考值不行吗?
答案是:绝对不行。
如果在控制代码里直接把 PLL.CntFianl 作为参考值,你的 PFC 控制系统不仅起不到功率因数校正的作用,甚至极有可能引发炸机。
要彻底理解为什么,我们必须搞清楚 “X 轴(时间/相位)” 与 “Y 轴(电流幅值)” 在控制逻辑中的本质区别:
1. PLL.CntFianl 只是“X 轴”(时间坐标)
PLL.CntFianl 在代码中的作用是一个累加器,随着时间推移,它在一个半周期内会均匀地从 0 逐渐增加到 1023。
如果在示波器上把 PLL.CntFianl 的数值画出来,你会看到一条斜直向上的直线(即锯齿波)。它仅仅代表时间的流逝或者说“角度进度”(比如:当前相位是 0度、90度,还是 180度)。2. 系统真正需要的是“Y 轴”(正弦波形)
PFC 的根本目的,是强迫电感里的电流波形完美跟随电网电压。
既然电网电压是正弦波,那么提供给电流环的“电流参考值”也必须是一个完美的正弦波。如果你直接把代表时间的 PLL.CntFianl 丢给电流环,系统就会拼命把输入电流控制成一个锯齿波。这完全违背了 PFC 吸收正弦电流的初衷,会对电网造成极大的谐波污染。3. 正弦表 sinetable 是从 X 到 Y 的“翻译官”
我们无法让时间(X 轴)直接变成正弦波的幅值,所以需要一个数学映射关系:$Y = \sin(X)$。
- 输入 $X$: PLL.CntFianl 就是这个函数里的输入变量 $X$(当前相位)。
- 执行 $\sin()$: 程序拿着 $X$ 去 sinetable 数组里查表,这个动作本身就是在执行正弦计算。
- 输出 $Y$: 从表里查出来的值(0 ~ 4095),才是最终需要的 $Y$。它明确告诉系统,正弦波在当前这个角度下,幅值究竟有多高。
前馈环控制设计理论与数字逻辑实现
前馈环控制设计理论与数字逻辑实现
函数名:void FeedCal(void)
电源控制中的前馈(Feedforward)机制,其核心思想是预先计算出一个稳态情况下的控制量大小,并将其作为基础基准直接提供给控制系统。在数字控制领域,由于受限于 DSP 主频的运行速度、采样与环路计算不可避免的延时,通常电流环设计的带宽并不能达到理想状态。仅靠纯闭环(如 PI 调节器)的纠差控制,系统往往存在响应滞后,无法实现电感电流对电网电压相位的精确无静差跟踪。
为了补偿电流环控制带宽的不足,我们可以利用既定的物理定律:根据输入电网电压与最终需要稳定控制的 DC 母线电压,结合 Boost 电路在 DCM(断续导通模式)与 CCM(连续导通模式)下的工作特性,提前计算出系统在当前瞬间稳态下的占空比(即前馈控制量)。
加入前馈量后,电流环就如同有了一个精准的“领航员”,主动为环路控制输出提供一个稳态工作点的控制量。这样一来,电流调节器的负担大幅减轻,其调节范围被极大地缩小在稳态点周围(只负责微调和抑制扰动),从而让被控电流的特性能够更加接近理想的正弦波形。
理想工况下的输入特性假定
为了推导前馈公式,我们首先假定当前系统运行的实际工况。输入电压与电流的物理参数如下:
计算输入电压的峰值:
假定输入电流有效值:
计算系统的输入功率:
构建输入正弦电压的半边绝对值函数表达式(因为 PFC 后级面对的是整流后的馒头波):
根据上述函数,我们绘制出输入电压在一个工频周期内的波形如下:
CCM 模式稳态占空比反推
根据 Boost 电路的基本工作原理,在电感电流连续的理想状态下(CCM 模式),占空比 $D$ 仅与输入电压和输出控制的母线电压相关。根据输出母线电压被控制在稳态,我们可以直接反推出系统在任何时刻需要的 CCM 占空比:
绘制出对应的 CCM 占空比波形如下:
DCM 模式的引入与推导
上述占空比计算的前提是 Boost 电路始终工作于 CCM 模式下。但在真实的 PFC 运行场景中,情况并非如此单一。特别是在交流输入电压的过零点附近,或者系统处于轻载状态时,电感中的储能较少,电感电流在每个开关周期结束前就会降为零,进入断续导通状态(DCM),如下图所示:
在 DCM 模式下,原有的 CCM 电压传输比公式失效,占空比不仅取决于输入输出电压,还与电感量、开关频率及负载功率强相关。根据 DCM 工作情况下的伏秒平衡与能量守恒定律,可以推论出 $D_{dcm}(t)$:
在上述推导公式中,各参数的物理意义如下:
- $D_{ccm}(t)$:PFC 工作于连续导通模式下的占空比;
- $D_{dcm}(t)$:PFC 工作于断续导通模式下的占空比;
- $V_{acpeak}$:输入电压的峰值;
- $P_{in}$:输入功率的平均值;
- $f_s$:系统的开关频率;
- $L$:PFC 主功率电感值。
全范围前馈占空比的融合策略
当 Boost 电路工作于我们设定的实际工况下时,其在 DCM 和 CCM 模式下所需的稳态占空比是不同的。我们将两种稳态工况下的占空比(前馈值)绘制在同一坐标系中进行对比:
如上图所示,红色实线为 BOOST 电路工作于 CCM 模式下的稳态占空比,蓝色虚线为 BOOST 工作于 DCM 模式下的占空比。
事实上,BOOST 电路在系统运行中,当电流较大(如正弦波峰值区域)时往往自然工作于 CCM,而在电流较小(如过零点区域)时退化工作于 DCM。因此,控制策略上我们取两者计算出的极小值,作为 BOOST 在整个工频周期范围内的稳态最终占空比(前馈量),即图中的绿色虚线。
相应的,我们设计的前馈计算程序流程图如下:
流程原理解析:
- 构建标准输入电压: 锁相环(PLL)输出的相位信号乘以峰值电压,即可构建出标准同步的正弦电压。
- CCM 前馈计算: 根据前面的公式,用 1 减去(正弦电压信号除以母线电压信号)获得 CCM 前馈占空比值。为了给闭环调节器留出微调空间,从而获取更好的 THD 与 PF 值,我们取理论 CCM 前馈值的 0.95 倍。
- DCM 前馈计算: DCM 前馈值等于在低频中断中算好的 DCM 前馈系数,乘以 CCM 前馈的开根号值。
- 软启动与择小输出: 比较两者大小取小者。同时,在启动阶段,为了抑制前馈量突然加入造成电感电流变化剧烈而误触保护,必须引入软启过程(乘以软启动系数)。
理论公式与 DSP 数字量定点换算验证
为了在 DSP 中执行上述物理公式,必须将其全部换算为无小数的定点数(Q格式)。下面是详细的换算推导与验证过程。
我们任意选取一个时刻 $tt$ 进行验证:
计算对应此时刻的输入电压物理值:
计算此时刻 CCM 模式下的理论占空比:
假设我们采用 Q15 格式(即 $100\%$ 满量程占空比对应的数字量为 32768),换算为 DSP 内部数字量:
对应此时的理论 DCM 占空比为:
DCM 占空比换算为数字量:
上面所有计算均是基于物理系统的实际标称值计算。但在代码中,所有变量都是通过 ADC 采样进来的数字量。下面推导如何通过 DSP 采样值直接得到前馈量。
原始 DCM 占空比物理计算公式为:
使用 DSP 采样的数字量并结合 Q15 格式进行映射表示:
对上述复杂公式进行常数项与变量项的剥离和化简:
提取出一个恒定的硬件环境常数 $K$:
代入对应的 ADC 采样基准与实际标称参数,我们可以得到验证方程:
可以看到,纯数字量映射计算出的结果($2.466 \times 10^4$)与直接用物理量算出来的 $D_{dspdcm}$ 完全一致,证明映射公式在逻辑上绝对成立。
规避 CPU 瓶颈:空间换时间的高速查表法
在实际应用过程的 DSP 计算中,sqrt 根号运算属于浮点库级别的复杂指令,极其消耗指令周期。如果在高频中断里直接开根号,会导致 CPU 严重过载甚至死机。为了避免时间资源消耗太大,我们在工程中大量使用根号查表法来获取对应的数据。
将上述计算 DCM 占空比数字量的公式进一步变形为适合查表的形式:
具体的定点移位与查表过程剖析:
CCM 占空比开根号 (Q15格式):
除以 $2^5$ (即右移 5 位) 是为了将数据压缩进 1024 长度的表格内:通过查表得到的放大数值:
输入电压开根号 (Q15格式):
查表得到:
输入电流开根号 (Q15格式):
查表得到:
计算系统功率开根号 (Q15格式):
计算峰值电压的倒数:
利用倒数可以将除法化为乘法。放大的倒数值:
硬件常数 K 值的预计算:
为了保留精度,将最终常数放大 Q10 倍(计算结果最后需要除以这个 Q10 还原):最终纯定点前馈输出:
根据上述离散化后的系数,可以直接进行简单的乘法和位移运算得到最终 DCM 占空比数字量:其结果与极尽耗时的浮点理论运算结果相差无几,但在 DSP 中的执行速度却呈指数级提升。
底层 C 语言控制程序代码展示与深度解析
为了支撑上述查表算法,我们在全局内存中预置了一个长度为 1024 的数组。其内容全部为提前运算好的 0-1 之间数值开根号后的定标整数:
1 | // 开根号查表 Q10 放大格式,数组大小1024,映射索引输入值与其对应的非线性根号值 |
在代码层面,FeedCal(void) 函数通过定标、位移以及预设常量的配合,巧妙地完成了理论中复杂的所有计算:
1 | /* |
整个流程没有任何浮点运算,全由移位和查表代替,使得 DSP 能够在微秒级的高频中断中轻松游刃有余地控制直流母线电压。
数字PFC开环传递函数模型和电流环设计及伯德图分析
数字PFC开环传递函数模型和电流环设计及伯德图分析
在数字功率因数校正(PFC)电源控制系统中,整体环路架构通常被设计为:慢速外环(母线电压环) + 快速内环(电感电流环) + 占空比前馈补偿 的复合控制结构。
其中,为了捕捉微秒级的电流瞬变,快速电流内环与占空比前馈计算都被布置在最高优先级的 ADC 硬件中断函数(ISR_ADC)中进行实时更新;而对外输出功率较为平缓的慢速电压外环,则被放置在 1kHz 的时间中断里进行计算。本章将详细拆解电流内环从“经典连续域控制理论模型”到“数字离散化 C 代码”的完整转换与实现过程。
系统常规数字标幺量与整体工作参数定义
在建立传递函数和展开数字算法之前,我们首先需将系统的标称参数进行物理和数字层面的统一。
常规数字量定义 (Q 格式基准)
DSP 在内部执行浮点除法极其消耗时钟周期,因此控制算法内部统一采用定点 Q 格式进行标幺化运算:
在本章节中,主要以 Q15 作为数据满量程运算标准,即 32768 代表 DSP 内部能处理的最大输入数字量。
PFC 工作整体硬件参数
- 交流电网输入电压(最低、额定、最高有效值):
- 定义 PFC 工作开关频率(对应采样与计算频率):
- PFC 主功率电感值:
- 额定母线控制电压与最大输出功率:
- 计算额定稳态输出电流和等效负载电阻大小:
- 定义输出直流母线滤波电容容值:
- 计算额定输入工况下的稳定工作占空比:
PFC 电流环开环传递函数与连续域建模
为了评估系统的稳定性并设计合理的 PI 补偿器,必须先建立连续域下的系统传递函数。工程上系统稳定要求相位裕度在45度以上,增益裕度为10dB以上,或者7dB以上
BOOST 电路主功率级小信号开环传递函数
在忽略 parasitic 寄生参数的前提下,构建 BOOST 电路从占空比小扰动 $\hat{d}(s)$ 到电感电流小扰动 $\hat{i}_L(s)$ 的开环传递函数(暂不包含 DSP 内部数字采样与发波环节):
利用上述公式,我们可以绘制出 BOOST 电路从占空比到电感电流开环传递函数的增益曲线和相位曲线:
(注:此处对应文档图中的第一组开环传递函数原始波特图,表现出典型的二阶谐振峰特性,其谐振频率取决于 $L_{PFC}$ 和等效滤波参数。)
数字控制内部完整环路架构与模型修正
实际的数字 PFC 电流内环整体架构不仅仅包含主电路,还结合了底层硬件的采样衰减、发波延时以及数字调理环节,其实际架构如下图所示:
图7.1 PFC电流内环整体架构与信号流向
如上图所示,各个子模块的传递函数物理意义定义如下:
- $G_{id}(s)$ 为系统从占空比至电感电流的连续域传递函数;
- $K_i(s)$ 为电感电流通过采样电阻、差分运放及 RC 低通滤波转换于 DSP 内部采样的传递函数;
- $G_{ci}(s)$ 为我们需要针对性设计的电流环补偿器传递函数;
- $G_{dly}(s)$ 为开关周期延时传递函数(在单周期控制中,由于 DSP 采样和算力耗时,PWM 寄存器更新通常会强行延时 1 个开关周期生效);
- $F_M$ 为环路数字输出至实际占空比的转换传递函数;
- $i_{ref}$ 为由外环和锁相环构建的参考电流指令。
因此,未补偿前整体系统的开环环路传递函数 $T_i(s)$ 为:
采样电路调理函数 $K_i(s)$ 的推导
定义 MOS 电流取样电阻、差分放大电路阻值、低通 RC 滤波参数如下:
由于 DSP 内部 ADC 采样的最高极值电压为 3.3V,在设计和数学推导中为了方便计算,将 DSP 内部满量程统一用标准值 1 代替 3.3V。由此归一化 MOS 电流采样与 DSP 内部采样的传递函数如下:
这里解释为什么公式最后乘以 $\frac{1}{3.3}$: 因为硬件采样电路将其转为了 0~3.3V 的模拟电压送入引脚,但在数学建模中,为了让传递函数与 Q15 标幺值(满量程为 1)对齐,必须除以 3.3 进行物理幅值的归一化。
采样计算延时与 PWM 更新传递函数 $G_{dly}(s)$
PFC 的 PWM 寄存器更新为了避免半周期竞争冒险,设定为一个开关周期的延时,定义延时传递函数为:
PWM 调制增益 $F_M$
DSP 内部所有计算均采用标定值 1,占空比输出也使用标定值,即 1 代表 100% 的满量程占空比,则:
剔除补偿器前的数字系统开环波特图与稳定性设计
设 $G_{ci}(s)$ 为需要设计的电流环补偿器。如果我们剔除该补偿器,统一将从占空比到电流 $G_{id}(s)$、电流采样转换 $K_i(s)$、占空比更新延时 $G_{dly}(s)$ 以及调制增益 $F_M$ 相乘,便可以得到补偿前的实际数字硬件开环传递函数:
PI 补偿器参数的精准求解
为了保证电流内环对工频正弦波的高频跟踪能力,同时避免在高频段被开关噪声干扰,我们定义补偿后的电流环传递函数 $T_i(s)$ 的目标穿越频率为:
通过代入计算补偿前传递函数在穿越频率处的幅值增益和对应的实际放大倍数:
传统 PI 补偿器的标准连续域传递函数为:
其中,$K_{ci}$ 为 PI 的增益,$\omega_{zi}$ 为传递函数需要求解的转折零点。
为了保障系统的绝对鲁棒稳定性,定义补偿后的电流环目标相位裕度为 50 度(实际计算取近似设计值)一般大于45就认为稳定:
根据 PI 传递函数的特性,为了达到此目标,则需要放置零点 $\omega_{zi}$ 在穿越频率 $f_{ci}$ 处产生的相位超前角度应为:
由此可以几何反推计算得到目标零点的频率位置和角频率位置为:
根据闭环穿越频率的概念,系统最终开环传递函数 $T_i(s)$ 在穿越频率点 $f_{ci}$ 处的总增益必须为 0 dB(即放大倍数为 1),也即是原始传递函数 $G_{idDSP}(f_{ci})$ 的增益乘以 PI 补偿器 $G_{ci}(s)$ 的值等于 1。因此可以构建对应模值平衡的非线性方程:
通过预设迭代 K 值,使用牛顿迭代求解算法求得绝对增益 $K_{ci}$ 值:
以此,便完全解解出了补偿器最终的频率特性传递函数为:
最终环路补偿伯德图分析
将上述解得的 PI 补偿器 $G{ci}(f)$ 与未补偿前的硬件系统 $G{idDSP}(f)$ 逐点相乘,即可得到补偿后最终系统完整开环传递函数 $T_i(f)$:
下图展示了完整的系统传递函数优化演演进伯德图:
波特图深入解析与验证:
- 第一组曲线 (极左上与右上) $G_{id}(f)$:仅仅包含了 BOOST 主电路。可以看到在 100~200Hz 之间有强烈的二阶谐振尖峰,超过此尖峰后以 -40dB/dec 的斜率迅速衰减,相位剧烈翻转至 -90° 以下。
- 第二组曲线 (极中上) $G_{idDSP}(f)$:这是叠加了硬件低通滤波 $K_i(s)$ 和 1 个开关周期延时 $G_{dly}(s)$ 后的真实数字硬件模型。可以看到在高频段(>10kHz),由于采样延时的非最小相位特性,其相位曲线急剧恶化(发生 360° 剧烈下翻)。若不设计正确的补偿器,系统在交叉频率处极易因相位滞后超过 -180° 而产生剧烈自激震荡!
- 第三组曲线 (极中下) $G_{ci}(f)$:这即是我们精心计算设计出的 PI 补偿器特性。他在中低频段提供了极高的积分增益(压制工频静差),并在 970Hz 左右注入了一个转折零点,把滞后的相位强行拉回升起。
- 第四组曲线 (极左下与右下) $T_i(f)$:最终闭环系统的开环响应!根据数学验证公式:这就完美证明了:系统在 3.5kHz 准确穿越 0dB 轴,实现了足够的带宽,并且在穿越点保留了健康的 46° 相位裕度 和 9.4dB 的高频幅值裕度!系统既能迅猛跟踪电网正弦电流,又对高频开关噪声表现出极强的免疫力。
电流内环数字参考指令构建 (IrefCal)
为了让 PFC 控制的电感电流不仅在波形上能够完美跟随电网电压的正弦包络线,同时还能稳定输出直流母线电压,参考电流指令 $I_{ac.Ref}$ 必须由三个变量进行立体构建:
- 输入电压相位信号 (
Vac.Sine):由上一章的 PLL 锁相环查表生成,负责为电流指令赋予“纯净同相的正弦波形状”。 - 外环电压环输出 (
Vloop.out):代表母线电压为了维持目标值所需要向电网索取的能量大小。当负载功率增加,Vloop.out变大,正弦参考电流的振幅随之整体长高。 - 输入电压有效值平方的倒数 (
Vac.Rmsover2):PFC 系统是一个恒功率控制系统 ($P_{in} \approx P_{out}$)。当用户端交流输入电压降低时,为了维持相同的输出功率,吸取输入电流的有效值必须成反比增大。因此在公式中,必须将参考值除以输入有效值的平方 $\frac{1}{V_{in.rms}^2}$。
综合上述规律,实际控制中的理论数学表达式为:
其中 $K_m$ 为乘法器校准系数,$K_{ss}$ 为抑制开机过冲的参考电流软启动系数。
代码具体逐行精析
1 | /* |
PI 电流环闭环调控与前馈融合 (CurrentLoop)
在获得精确的参考指令 Iac.Ref 和高精度的实际 MOS 电流采样值 SADC.Imos 后,便进入了微秒级内环最核心的运算阶段:PI 闭环纠差 + 前馈融合输出。
整个计算控制逻辑流程极其清晰严密,其标准程序流程如下图所示:
代码具体逐行精析
1 | /* |
数字PI环路参数自适应矫正与寄存器更新
数字 PI 环路参数自适应矫正与寄存器更新
在完成了电流内环开环频域建模、PI 补偿器基础参数推导以及占空比前馈计算之后,系统控制便进入了面向硬件底层的调试与适配阶段。
上一章求得的 PI 补偿器参数基于理想恒定电感下的额定工况。然而,在实际的高频大功率 PFC 运行中,主电路电感量并非绝对恒定,它会在不同电流偏置下发生动态非线性衰减;同时,为了结合占空比前馈量获取极致的总谐波失真(THD)与功率因数(PF)表现,我们需要让数字 PI 调节器的比例系数 $K_p$ 与积分系数 $K_i$ 具备跟随实时输入负载电流变化的变增益自适应矫正能力。
本章将详细阐述 PI 连续域参数如何转换为离散数字量、变增益自适应函数的推导过程,最终把求解出的 Q15 标幺占空比安全写至底层的 EPWM 发波寄存器。
连续域 PI 参数的数字化与定点缩放
在将控制论中的 S 域 PI 补偿器植入微秒级运行的 C 语言中断前,必须通过差分方程原理进行离散化,并针对 DSP 内存的定点数进行 Q 格式定标。
连续域到离散域位置式 PI 转换
我们将 PI 补偿器传递函数表示为标准的物理位置式传递函数(其中 $K_p$ 为比例系数,$T_i$ 为积分时间常数):
根据代数恒等关系,可以提取得到对应的绝对 PI 比例系数:
积分的时间常数相应为:
已知 PFC 系统核心电流环的采样与计算执行周期为:
结合前向欧拉离散积分原理,可得到数字化的实际积分增益参数:
DSP 内部 Q13 定标处理
数字 PI 控制中,如果调节系数过小(如 0.17),在定点整数乘法运算中会被严重截断从而失去精度。因此,我们将 PI 控制的比例和积分系数统一放大 Q13 倍(即乘以 $2^{13} = 8192$),使其以无损整数形式参与硬件运算:
电流环非线性变增益 PI 矫正设计
上述计算出了基于 PI 环路控制的电流环标准基础补偿过程。但在实际工程应用中,为了达到较好的电流 THD 值并协同前馈控制发挥最大效能,必须对 PI 环路参数进行经验与物理特性的非线性矫正。
为什么需要变增益?核心物理背景分析:
在 PFC 实际运行过程中,铁粉芯或非晶磁粉芯主电感的感量会随着流过电流大小的变化而发生改变 —— 在重载(大瞬时电流)情况下,电感铁芯渐进饱和,实际电感量比轻载情况会有显著衰减。
根据被控对象增益与电感成反比的物理规律(电感小,电流爬升快,开环增益大),如果全功率范围维持同一组强劲的 PI 参数,大电流区往往容易发生高频震荡或电流毛刺;相反,如果全区间使用稳妥保守的参数,轻载和过零点处电流环又显得无力,无法拉平交越失真。
因此,我们可以设置电流环的 $K_P, K_I$ 参数随着实时输入电流绝对大小进行相应的变增益动态衰减计算!
变增益锚点设定
定义轻载(瞬时小电流)情况下的初始 $K_p$ 和 $K_i$ 基础参数:
我们挑选需要进行变增益线性插值的两个典型输入电流校准点位 0.5A 和 2A(以 10A 作为系统最大检流满量程标定值):
定义在这两个关键电流锚点上对于比例系数 $K_P$ 的目标期望值(大电流衰减为原来的二分之一):
同样,定义这两个电流锚点上对于积分系数 $K_I$ 的目标期望值:
变增益自适应线性方程求解
通过上述设定的物理坐标点,利用两点确定一条直线的原理,可构建 $K_P$ 随电流变化的线性矩阵方程:
运用矩阵求逆联立求解方程,得到直线的理论斜率 $K_{pK}$ 与截距 $K_{pB}$:
为了在 DSP 单片机中用整数乘法高效算出斜率,我们将理论斜率进一步放大 Q12 倍:
同理,构建 $K_I$ 参数随电流变化的方程矩阵:
求解该直线对应的斜率与截距,同样将其斜率在 DSP 内存放 Q12 倍:
最终,我们便成功构造出了在 C 语言中断中调用的两个高动态变增益自适应函数:
将假设的输入电流点代入验证:当输入电流恰好为 $0.5\text{A}$ 时,
结果与期望初始锚点严丝合缝,验证了自适应数学转换方程的精准性!
动态增益极值安全钳位与特性曲线
为了保障系统绝对安全,避免电网突变瞬态产生极端的负向增益或过大增益,必须对计算出的变增益输出施加严格的最大、最小值上下限限制:
绘制出动态调校后,电流环比例系数与积分系数对瞬时输入采样电流变化的自适应响应曲线如下:
从曲线上可直观看到:当电网正弦波处于过零点及轻载区间(横轴采样值极小),PI 调节器自动释放最大增益,强力拉紧波形;而随着正弦波走向峰值大电流区(横轴采样值变大),PI 增益如预期般平滑线性下移,精准适配了主电感在高磁密下的感量衰减,从根本上消除了峰值附近的电流毛刺与震荡!
PWM 寄存器更新控制 (RegReflash)
经过电流内环算法计算出来的最终输出量 ILoop.out 是一个标准的 Q15 标幺量(即数字量 $2^{15} = 32768$ 代表实际占空比 $100\%$)。微处理器硬件无法直接认识标幺值,我们须将占空比标量转换并映射成实际能够驱动外围管脚的高频 EPWM 比较寄存器值。
同时,为了支持各类软件保护(如硬件过流 OVP、软件过压、软关机等),系统环路中引入了独立的运行标志位 Flag.PWM 用以实时启动和关闭发波。
根据底层发波机理,控制规则为:当 Flag.PWM 标志位为 0 时,无论环路计算出的占空比 ILoop.out 为何值,发波寄存器的比较器门限必须立刻重置为满周期计数值,使高电平脉冲彻底消失,即发波强制关断。
代码具体逐行精析
1 | /* |
DCM电流采样矫正与硬件过流保护
DCM电流采样矫正与硬件过流保护
在 PFC 的控制策略中,我们采用的是平均电流控制法,其核心反馈量是电感电流的“平均值”。然而,在实际的单片机 ADC 采样中,我们往往只能在特定的时间点去“窥探”电流的瞬时值,进而推算出平均值。
这就引发了一个工程界极其经典的物理难题:在连续导通模式(CCM)下,采样逻辑是完美的;但在断续导通模式(DCM)下,由于电流波形发生了畸变,传统的采样点会抓取到错误的偏高数值。同时,复杂的矫正运算又会给 DSP 带来极大的算力负担。
本章将详细解析 DCM 采样的物理误差根源、倒数查表法的降维打击优化,以及周波级硬件过流保护(CBC-OCP)的软件接管逻辑。
DCM 电流采样的物理困境与误差分析
在数字 PFC 控制中,ADC 的触发点通常设置在 PWM 发波开启时间(ON-time)的正中间。
- 在 CCM(连续模式)下:电感电流是一个连续的梯形波(或完整三角形)。根据几何对称性,在其上升段的 50% 处进行采样,抓到的瞬时值 $i_{sense}$ 刚好等于整个开关周期 $T_s$ 内的电流平均值 $I_{in}$。
- 在 DCM(断续模式)下:电感电流在开关周期结束前就已经掉到了 0,并保持了一段死区时间。
如下图所示:
从波形图上可以清晰看出,由于死区时间的存在,真实电流波形的“物理中心”向左偏移了(采样中心点会偏左)。此时如果我们依然死板地在 PWM 导通时间的 50% 处去采样得到 $i_{sense}$,这个采样值仅仅是那个“瘦高三角形”的平均值,而远大于整个周期 $T_s$ 平摊下来的真实平均电流 $I_{in}$。
如果 DSP 直接拿这个虚高的假信号去闭环,就会误以为输入电流已经很大了,从而错误地压低占空比,导致交越失真严重,THD(总谐波失真)急剧恶化!因此,必须通过数学手段将这个虚高的采样值“打折”矫正回真实的平均值。
矫正系数的数学推导与“查表代除法”优化
根据伏秒平衡与几何面积等效原理,可以推导出现实采样值与真实平均值之间的矫正系数 $I_{cal}$ 公式:
根据上述公式进行分类讨论:
- 若系统工作于 CCM 模式: 此时实际占空比 $D = D_{ccm}(t)$。由于理论上 $D_{ccm}(t) = \frac{V_o - u_{in}(t)}{V_o}$,代入原式约分后 $\Rightarrow I_{cal} = 1$。说明采样值即为平均值,无需打折。
- 若系统工作于 DCM 模式: 此时实际占空比 $D = D_{dcm}(t)$,代入公式后得到动态矫正系数:
工程痛点与神来之笔:
在 DSP 内部实时计算上述 $I_{cal}(t)$ 极其困难,因为公式中不仅包含实时的占空比变量,最要命的是它包含了一个极耗 CPU 时间的除法运算(分母是随时变化的输入电压)。
为了避免高频中断里的除法导致系统崩溃,程序员极其巧妙地利用了前面算好的前馈量,并结合倒数查表法进行了降维打击:
仔细观察公式:$\frac{V_o}{V_o - u_{in}(t)}$,这恰好是理论 CCM 占空比 $D_{ccm}(t)$ 的倒数!
所以公式可以完美转换为:
为此,代码中预置了一个专门存放倒数放大值的 Q5 格式查表数组 DIV_TABLE。我们只需拿当前的理论前馈占空比 Feed.ccm 去查这个表,瞬间就能得到极其耗时的除法结果。
1 | //倒数查表 Q5 |
软件矫正逻辑与代码精析
真实的矫正逻辑并不盲目,而是带有极强的工程经验考量:
- 软启动屏蔽:在软启动过程中,系统状态极不稳定,此时不计算 DCM 电流矫正值(系数强置为1),防止矫正干扰正常起机。
- 轻载屏蔽:由于轻载时电流本身就很小,微小的偏差对波形影响不大。出于效率和稳定考量,“轻载一般不矫正,一般都是半载以上”才介入矫正(即输入低功率标志位
Flag.LowP == 1时系数置1)。 - 平滑过渡屏蔽:为了保证 DCM 向 CCM 模式跨越时的计算平滑,当算出的矫正系数超过 0.9 时,直接强制取 1。这一过程极大削弱了跨越边界时的电流过冲。
结合流程图,我们可以清晰看到这一判断逻辑:
具体落实到 C 语言代码中,精简而高效:
1 | /* |
硬件周波级过流保护 (CBC-OCP) 软件接管
除了对电流进行精准的控制与矫正,在极端异常工况下(如电网浪涌、雷击瞬态或输出短路),纯软件代码的响应速度是绝对来不及保护 MOS 管的。
因此,我们采用了硬件级保护机制(TZ,Trip Zone)。当 MOS 电流触及硬件比较器阈值时,DSP 底层硬件会瞬间(纳秒级)自动切断 PWM 波,这就是所谓的“周期封波”或逐周期限流(Cycle-By-Cycle, CBC)。
但纯硬件封波也有弊端:它可能会被短暂的噪声毛刺误触发。因此,我们需要软件的 HwOcp(void) 函数来“监听”硬件的封波动作,进行智能的二次研判:是偶然的毛刺,还是真正的严重故障?
1 | /* |
电压环变增益与软启动
慢速外环1kHz中断处理:电压环变增益与软启动
在 PFC 数字控制系统中,通常采用双环控制架构:快速的电流内环与慢速的电压外环。前面章节我们探讨了布置在 ADC 高频中断里的电流内环,而本章将把视角转向运行在 1kHz 定时器中断里的电压外环。
由于母线大电容的存在,直流输出电压的变化相对缓慢。因此,电压环无需以几十千赫兹的超高频率运行,1kHz 的处理频率足以兼顾控制精度与 CPU 算力分配。本章将详细解析 1kHz 中断的调度逻辑、母线电压滤波、应对负载突变的非线性变增益控制,以及保障系统安全开机的多重软启动机制。
1kHz 中断架构与调度流程
在 DSP 的时基管理中,1kHz 中断由 Timer0 定时器周期性触发产生。为了保证电流内环(几十kHz)的绝对实时性,1kHz 的慢速中断被配置为可被 ADC 快速中断嵌套运行的低优先级中断。这意味着当 1kHz 中断正在执行复杂的电压环计算时,如果 ADC 采样完成,CPU 会立刻打断当前任务,优先去执行电流环闭环,等电流环算完再回来继续执行电压环任务。
下图展示了 1kHz 中断内部的完整调度时序:
具体的 C 语言中断入口函数实现如下:
1 |
|
母线电压的滑动平均滤波 (VbusAvgCal)
电压环作为外环结构,本质上是一个慢速环路,它对母线电压采样的实时性要求较低,反而对信号的平稳度要求极高。如果不加滤波直接送入 PI 调节器,母线上的高频开关纹波或工频纹波会被放大,导致电流参考值抖动。
因此,代码中对母线电压采样求取了 4 次滑动平均,以得到较为平稳的母线电压反馈值。
1 | void VbusAvgCal(void) |
电压环非线性变增益控制 (VloopKpKiCal)
由于电压环运行速度较慢,当输出端发生剧烈的负载突变(如满载突然切空载,或空载突然加满载)时,正常的 PI 电压环往往无法快速响应并抑制母线电压的突增与突减。这种迟滞极易造成母线触发硬件过压(OVP)或欠压(UVP)保护,导致系统宕机。
为了解决这个痛点,引入了非线性变增益控制策略:
- 甩负载突变(重载突变至轻载):此时多余的能量无处释放,导致母线电压快速拉升。当检测到母线电压大于设定的上限阈值时,程序瞬间将电压环 PI 参数增加 4 倍,使电压环输出快速递减,通过快速降低电流参考值,强力抑制母线电压持续增加。
- 加负载突变(轻载突变至重载):此时能量供应不足,母线电压快速拉低。当检测到母线电压低于设定的下限阈值时,程序将电压环 PI 值增加 2 倍,使电压环输出快速递增,通过快速增加电流参考值使母线电压迅速恢复。
- 稳态恢复:需要特别注意的是,当输出电压重新回到特定的稳定偏差范围内时,必须立即恢复常规的电压环 PI 参数,以避免过大的 PI 增益引起电压环的低频振荡。
下图展示了这一逻辑的判断流程:
具体的工程代码实现如下(同时注意:在系统开机启动过程中,母线电压处于动态爬升状态,尚未工作于稳态,因此必须屏蔽变增益功能):
1 | // 定义常规状态下的 KP 和 KI 标幺值 |
渐进式多重软启动机制 (Soft-Start)
为了防止 PFC 在启动瞬间由于巨大的压差导致严重的浪涌电流(Inrush Current)和电压过冲,程序中分布了多维度的软启动逻辑。
母线参考电压渐进软启 (VrefCal)
该函数主要负责处理电压参考值缓慢增加的功能。如果开机瞬间直接将参考电压设为 380V,巨大的电压偏差会瞬间将 PI 调节器积分饱和,造成危险的电流指令脉冲。因此,通过软件代码让参考电压阶梯式慢慢爬升,能有效避免电压参考值跳变引起的开机振荡。
1 | /* |
电流参考值与前馈量比例软启 (Irefss & Feedss)
除了参考电压的柔性爬升,直接作用于占空比控制的底层变量——电流参考量 (Iac.RefssK) 和 前馈占空比补偿量 (Feed.ssK),也加入了从 0 到 1 (标幺值 32767) 的乘法软启系数机制。
它们在每次 1ms 中断中以固定步长递增,最终放大至全量程,以此控制功率管从极窄脉冲开始慢慢张开,彻底杜绝了硬启动带来的声光火花。
1 | // 电流参考软启增量减量步长 |
PFC数字电压环补偿器设计
PFC数字电压环补偿器设计
在数字 PFC 控制系统中,除了内环(电流环)需要保证输入电流具有较好的 THD 值和 PF 值之外,外环(电压环)的控制目的则是保证输出母线具有稳定的电压值。本章将详细解析从 PFC 功率级等效模型推导、外环传递函数构建,到 PI 补偿器参数计算及 C 语言代码实现的全过程。
电压环的控制逻辑与程序流程
电压环的核心任务是生成电流环的指令幅度基准。电压环的输出量被用以构建电流环的电流参考值:
- 当母线电压低于参考值时,电压环输出增加,进而使内环电流环的参考量增加,促使输入电流增加以补充母线能量。
- 当母线电压高于参考值时,电压环输出减小,内环电流环参考量随之减小,输入电流减小,从而保证母线电压最终等于目标参考值。
下图展示了电压环的基础程序判断与执行流程:
PFC 电压 Control-to-Out 传递函数推导
为了设计电压环的 PI 补偿器,首先需要获取 PFC 主电路的功率级传递函数(即从控制量到输出电压的传递函数)。
PFC 功率级等效电路模型
PFC 的小信号等效电路模型如下图所示:
模型中相关电路参数的定义如下表所示:
根据等效模型提取出的核心参数表达式如下:
- 电压传输比:$M = \frac{V_o}{V_{in}}$
- 等效输入阻抗:$r_i = \frac{M^2}{r_o}$
- 控制增益参数:$g_i = k \cdot V_{in}$
- 控制增益参数:$g_f = \frac{2 \cdot V_c}{M}$
- 输出受控流源增益:$g_c = \frac{k \cdot V_o}{M^2}$
- 等效负载阻抗:$r_o = \frac{V_o}{I_o}$
功率级传递函数
当输入电压保持不变时(忽略前馈扰动),从控制量 $V_c$ 到输出电压的开环传递函数可以简化表示为:
将 $g_c$ 与 $M$ 的表达式代入,后续我们将通过整机控制架构推导出系数 $k$ 的物理意义。
PFC 电压环路控制架构与系数求解
电压环基础架构
在宏观层面,PFC 控制电路中的电压环路架构如下图所示:
其中:
- $G_{vc}(s)$ 为从控制量到输出电压的传递函数。
- $G_{cv}(s)$ 为我们需要设计的电压环补偿器传递函数。
- 未补偿的系统环路传递函数:$T_v(s) := K_o(s) \cdot G_{vc}(s) \cdot G_{cv}(s)$。
内外环耦合控制架构
配合前面章节讲解的电流内环控制架构,整个 PFC 的电流内环与电压外环双闭环控制架构如下图所示:
从图中可以提取出以下关键转换环节:
- $K_o$ 为输出电压的硬件分压与 DSP 采样传递函数。
- $K_{in}$ 为输入电压的硬件分压与 DSP 采样传递函数。
- 电压环路的输出量 $v_c$ 乘以输入电压得到电流环的参考电流 $i_{ref}$,其中 $K_m$ 为乘法器增益。
- 为了加快电压环路对电网波动的抑制效果,引入了输入电压前馈控制,即除以输入电压有效值的平方(除法器系数 $K_{ff}$)。
未知系数 $k$ 的推导
根据 PFC 的工作原理,当系统工作于稳态时,输入电流平均值等于参考电路平均值。同时满足等效受控源公式:
(其中 $k$ 为待求解系数)。
从 PFC 整体的控制架构图中,根据信号流向可以写出电感电流指令的表达式:
(其中 $v_{in}$ 为输入电压瞬时值,$V_{in}$ 为有效值,$V_c$ 为电压环输出量,$K_i$ 为MOS电流转换和采样增益)。
在稳态下,使用平均值代替瞬时值,则推算出真实输入电流为:
将该式与 $I_{in} := k \cdot V_{in} \cdot V_c$ 对比,即可推算出系统核心系数 $k$ 为:
将解得的 $k$ 代入输出受控源增益 $g_c$:
最终带入传递函数,得到完整的电压极点传递函数:
实际数字量参数求解与模型实例化
下面开始求解上述传递函数中对应的相关硬件变量。由于电压环的处理速度(1kHz)比电流环(45kHz)慢数量级,其穿越频率通常在 10 ~ 30Hz 左右。因此在这个极低频段内,所有输入输出电压的采样硬件滤波延迟和运算延时均可以忽略不计,只取直流分量:
- 输入电压采样增益:
- 电流采样增益:
- 输出母线电压采样增益:
根据输入功率的关系平衡式:
在实际的数字控制中,对相关的变量和参数进行标定的话,我们取电压环输出最大值 $V_c$ 的稳态工作点约为 0.7:
为了简化计算,设置前馈标幺基准 $K_{ff}$ 等于采样基准:
假定满载理想无效率损失,输入功率等于输出功率:
代入公式计算得到乘法器增益 $K_m$ 的绝对物理值为:
DSP代码映射:
由于在 DSP 中采用 Q15 定点格式代表小数(放大 32768 倍),我们在代码里使用的 IREF_KM 宏定义即由此而来:
同时,额定母线电压设定为:
代入后,我们便得到了基于实际电路参数的控制到输出电压功率级真实传递函数 $G_{vc}(s)$。
PI 电压环补偿器设计与零点极点配置
由于 PFC 系统固有的特点,为了不过度放大母线上的 100Hz 工频纹波,电压环带宽必须设置得很低。
- 定义补偿后的电压环传递函数 $T_v(s)$ 的目标穿越频率为:
- 计算补偿前原传递函数在目标频率的增益和对应的实际放大倍数:
- 设定传统 PI 补偿器的传递函数:(其中,$K_{cv}$ 为 PI 增益,$\omega_{zv}$ 为需要求解的零点角频率)
- 定义补偿后的目标相位裕度为 45 度:
- 根据 PI 传递函数特性,零点 $\omega_{zv}$ 在穿越频率处需产生的相位超前角度为:
- 计算得到零点频率的位置:
- 根据闭环穿越频率的概念,穿越频率点的总增益为 0dB(即放大倍数为1),据此构建方程求解出补偿器绝对增益:
结合上述计算,我们得出了完整的开环系统波特图,展示了系统补偿后在极低频(10Hz)依然具有出色的稳定性和 45 度的健康相位裕度:
S域连续参数到数字定点变量的换算
为了在 DSP 中执行计算,需要将 S 域传递函数离散化,并缩放为 C 语言中的整数。
将 PI 补偿器转换为经典位置式传递函数公式:
提取对应的 PI 比例系数和积分时间常数:
系统电压环运行在 1kHz 中断中,因此其实际采样周期为:
得到数字化的实际积分常数:
DSP Q10 定标放大:
由于积分参数 $0.174$ 太小,不便于单片机计算,我们将其人为放大 Q10倍(即 $2^{10}=1024$),并四舍五入为纯整数,这便是代码宏定义中的最终参数源头:
C 语言代码实现与精析 (VoltageLoop)
经过复杂的建模和推导,最终在代码中的落地实现却非常简洁。通过 Q 格式的高精度移位,保证了积分的精度与计算速度。
1 | // 定义常规状态下的 KP 和 KI 标幺值 (基于上述推导理论值进行的工程微调) |
PFC过压保护与欠压保护
PFC 母线电压保护与交流有效值高精计算
在数字 PFC 电源控制系统中,除了实现高功率因数的核心闭环控制外,完善的安全保护机制与精准的系统状态感知同样不可或缺。
本章将深入解析三个关键的后处理模块:母线电压过压限制(OVP)、母线欠压故障保护(UVP),以及基于半波积分法的交流电压与电流有效值(RMS)高精计算。
软件级母线电压过压限制 (VbusLimit)
电压环的根本任务是保证公共直流母线电压稳定工作于规定范围内。然而,当电网发生剧烈波动或系统遭遇极端甩负载(如满载瞬间切空载)导致控制短暂失调时,母线电压可能会异常过高。
如果仅依靠外环 PI 的线性调节,可能无法及时压制这种上升趋势,从而对后级变换器及母线电容造成过压损坏危险。因此,需要引入独立于 PI 之外的滞回比较过压限制机制。
过压抑制与恢复逻辑
- 过压触发:当系统检测到母线电压大于设定的过压阈值时,程序立即将过压标志位置位,并瞬间强制关闭 PWM 发波。为了防止系统恢复时产生巨大的突变冲击,程序会同步将参考电流的软启动系数清 0,并将电流环的积分累加器清 0,确保系统复位时必须重新进行电流软起。
- 安全恢复:当母线输出出现过压封 PWM 后,母线失去能量供给,输出电压因自然放电或负载消耗下降至合理安全范围,此时系统清除过压标志位,重新打开 PWM,恢复闭环控制。
其软件过压保护的程序判断流程图如下所示:
C语言代码精析
1 | /* |
母线欠压故障保护 (VbusUVP)
除了电压过高,公共直流母线电压异常偏低同样属于严重故障。当输出载过重或 MOS 管发生损坏失效时,母线电压会过低。
PFC 具备输出母线电压检测欠压保护功能。正常工作状态下,Boost PFC 的输出直流母线电压绝对不可能低于输入交流电经过桥式整流后的自然直流峰值。一旦检测到母线电压不仅没升上去,反而跌破了自然整流的理论下限阈值,即可断定系统已严重故障。
当检测到电压过低(低于自然整流电压时),发生欠压保护,PFC 将关闭 PWM,置位欠压保护标志位,强制切入故障保护状态,并通知后级停机。
其程序流程图如下:
C语言代码精析
1 | /* |
交流电压与电流有效值精准计算 (VIacRmsCal)
在闭环控制与前馈推演中,交流电压和电流的有效值(RMS)和峰值(Peak)是至关重要的参考基准。由于交流电是随时间不断波动的正弦波,传统方法如果强行在高速中断里离散开平方求有效值,会极大地拖垮 CPU。
为此,工程上采用了基于半周期离散积分的绝对平均值转换法。
算法数学原理推导
有效值计算基于正弦波计算方式。在 ADC 快速中断锁相环处理中,我们在每个工频正半周期内对采样电压和电流进行累加求和。
若每个中断计数点 $n$ 对应的绝对采样值为 $X_n$,则半个周期内的数字平均值为:
基于标准正弦波计算理论(正弦波有效值与平均值的关系、有效值与峰值的关系),完美正弦波的绝对平均值 $\bar{X}$ 与有效值之间存在固定的比例转换系数($\frac{\pi}{2\sqrt{2}}$)。通过将累加求出的平均值乘以该固定的转换系数,可以直接计算得到电压与电流的有效值与峰值。随后,再额外对有效值进行 8 次滑动平均滤波以熨平抖动。
该算法巧妙避开了离散求平方再开根号的复杂计算,其计算流程如下图所示:
代码实现与 Q14 定标精析
在实际代码中,为了避免浮点运算,需要将转换系数转化为 DSP 可以高效处理的定点整数。代码采用 Q14 格式 进行定标(即放大 $2^{14} = 16384$ 倍):
- 平均值转有效值系数:$\frac{\pi}{2\sqrt{2}} \times 16384 \approx 18198$
- 有效值转最大值系数:$\sqrt{2} \times 16384 \approx 23166$
1 | /* |
DCM模式下占空比前馈系数计算
DCM模式下占空比前馈系数计算与数字验证
在之前的章节中,我们在高频的 ADC 中断内完成了电流环的瞬时闭环与占空比的前馈叠加。但为了极大地节省微秒级高频中断的 CPU 算力,我们将 DCM 占空比前馈公式中变化缓慢的系数部分(如功率平均值、电压峰值的倒数)抽离出来,放置在 1kHz 的慢速中断中进行计算。
本章将详细结合前馈计算的物理数学原理,深度剖析 DCM 模式下前馈系数(Feed.dcmK)的纯数字标幺化提取过程、查表法开根号验证、起机安全限幅机制以及轻载屏蔽逻辑。
前馈参数计算的数学理论与波形绘制
在进行数字代码推导前,我们首先从宏观物理公式上验证 DCM 前馈计算的准确性。计算输入电压的峰值和假定输入电流:
计算系统的输入功率:
构建输入正弦电压的半边绝对值函数表达式:
绘制出的半边正弦电压理论波形图如下:
根据 Boost 电路工作原理,计算假设工作于 CCM 模式对应的稳态 CCM 占空比:
根据 Boost 电路工作于 DCM 状态下时,计算对应的 DCM 工作占空比:
在实际控制中,取两者的最小值作为系统控制的最终稳态前馈占空比:
分别绘制 BOOST 电路工作 CCM 占空比、DCM 占空比,与两者取最小值后的最终前馈对比图如下:
DSP 数字计算量标幺化推导与验证
上述计算的参数均为实际物理参数,下面我们将展示对应 DSP 内部标幺数字量的严格计算验证过程。
选取任意时间点 $tt$ 时刻,计算对应此时对应的输入电压:
计算此时的 CCM 模式下理论占空比:
在 DSP 中,如果 Q15 对应的占空比为 100%,则换算占空比的纯数字量:
对应此时的理论 DCM 占空比及其数字量为:
数字标幺化化简全过程
上面所有计算均基于物理实际值计算,下面推导如何通过 DSP 采样值的全数字标幺形式直接计算前馈。
原始计算公式为(参数为实际值):
将其完全使用 DSP 采样的数字量表示(引入 Q15 基准):
对方程进行移项与化简得到:
将常数部分提取为系数 $K$:
代入对应的硬件标称参数进行等式验证(结果与理论物理推演完美吻合):
规避开方运算:查表法转换
在实际应用过程的 DSP 计算中,使用 C 语言标准库的根号运算会占用极大的时间资源。为避免中断超时,必须使用根号查表法(利用上一章预设的 sqrttable)获得对应的数据。
将上述计算 DCM 占空比数字量的公式进一步变形为适合查表的格式:
根号查表法分步验证:
根号查表法计算 CCM 占空比开根号 Q15 (先右移5位适配 1024 长度数组):
根号查表法计算电压开根号 Q15:
根号查表法计算电流开根号 Q15:
根号查表法计算功率开根号 Q15:
计算峰值电压倒数:
计算公式中的常数部分 $K$ 值,并人为放大 Q10 倍(最终代码运算结果需除以该倍数):
最终,根据上述数字化的离散标幺参数,通过纯移位乘法得到 DCM 最终占空比量:
可以看到,最终得出的 $2.4379 \times 10^4$ 其结果与最初理论推导的 $2.466 \times 10^4$ 结果极其相近,完美验证了降维查表法的可行性!
软件保护流程设计:限幅与轻载屏蔽
在上一章节前馈计算原理分析中可知 PFC 工作 DCM 模式下的前馈量为:
我们将公式中剥离出的常数与慢变项(如功率平方根、电压峰值倒数)定义为 DCM 前馈系数,它与输入电压峰值与输入功率大小有关。
在工程实践中需要注意以下保护:
- 防爆计算限制:上电初期,有效值计算并非达到稳定值,电压峰值较小。由于电压峰值在除法计算的分母位置,为保证 DCM 倒数计算不失真而导致结果无限大(除以零或极小值),必须对起机时的有效值峰值进行强制下限限制。
- 轻载屏蔽前馈:同时在轻载的情况下,由于整个电网相角范围内电路均处于极深的 DCM 模式,信号信噪比差。因此,当检测到负载为轻载时,强制屏蔽前馈计算功能(赋值为0),交由 PI 环接管控制。
其完整的计算程序流程图如下:
C 语言核心代码精析 (DCMFeedCal)
根据上述推导,该函数位于 1kHz 的慢速中断中,利用查表、右移等手段高效合成了供底层微秒级中断使用的稳态 DCM 系数。
1 | /* |
电流环变增益
PFC 电流环变增益与软启动控制设计
在数字 PFC 电源控制系统中,电流的参考指令时刻跟随着电网电压的相位进行快速的正弦变化。然而,受限于数字信号处理器(DSP)的主频算力、硬件采样延时以及环路本身的物理惯性,数字控制的带宽频率往往无法做到无限高。
为了在有限的控制带宽下,既能保证极低的输入电流总谐波失真(THD),又能防止系统在复杂工况下发生过冲震荡,我们需要引入两大核心高级控制策略:电流环 PI 变增益自适应控制与前馈及参考指令的软启动控制。本章将对这两个模块的物理机理、数学推导及代码实现进行全方位深度解析。
电流环变增益的物理意义与数学推导
在实际应用中,由于磁芯材料的物理饱和特性,PFC 主电感在整个工作范围内的感量并非是完全恒定不变的,而是会随着流过电流的增加导致磁导率下降,进而使得感量逐渐减小。
当电感感量逐渐减小时,被控对象的开环增益会变大,这意味着如果维持原有的 PI 参数,电流闭环的相位裕度会逐渐减小,系统极易在正弦波峰值的大电流区域发生高频振荡。因此,我们必须根据输入电流的大小适当地动态减小电流环的 PI 参数。
当输入电压越低且输出满载时,输入电流越大,对应的电感感量也就越低;即电流环的 PI 参数必须根据输入电流的实时大小进行反比例的线性缩放变化。
初始轻载点位与标定锚点选取
根据先前的 PI 环路计算,我们首先定义在轻载(电流较小)情况下的初始 $K_P$ 和 $K_I$ 数字标幺参数:
由于系统设定的最大检流满量程为 10A,我们定义需要进行增益插值的两个关键输入电流点位(0.5A 和 2A)并转换为 Q15 标幺值:
分别定义这两个电流变增益点对应的 $K_P$ 目标值(大电流衰减至一半):
定义变增益点对应的 $K_I$ 目标值:
线性方程构建与斜率求解
为了得到连续的变增益函数,利用两点决定一条直线的原理,构建 $K_P$ 变增益点对应 $X$、$Y$ 矩阵:
通过矩阵求逆解算出该衰减直线对应的理论参数(斜率 $K_{pK}$ 与截距 $K_{pB}$):
由于斜率小于 1,在单片机中直接计算会丢失精度,因此将该参数放大 Q12 倍储存在 DSP 宏定义中:
同理,构建 $K_I$ 变增益点的对应矩阵并求解直线参数:
对应的 DSP 放大 Q12 倍参数为:
最终自适应函数与保护限幅
由此,构建出了跟随输入电流实时动态偏置的 $K_P, K_I$ 参数函数:
将 0.5A 假定值代入验证,完美契合初始目标点:
为防止计算溢出,对变增益的最大与最小值施加严格的安全限幅:
最终绘制出的电流环 $K_P$ 和 $K_I$ 数字量对输入电流数字量的动态平滑衰减曲线如下:
变增益控制代码精析 (IloopKpKiCal)
该函数放置在中低频的环路调度中,利用简单的移位与乘法,实现了上述复杂的理论自适应衰减数学模型。
1 | /* |
前馈与电流参考的软启动控制 (Feedss & Irefss)
优秀的电源不仅要在稳态运行中表现优异,在起机瞬间更不能对电网和后端元器件造成致命的电流过冲冲击。
前馈软启 (Feedss)
精确的前馈量能够使得电流环的输出控制性能得到极大提升。由前述章节可知,前馈量为预先计算得到的理论稳态工作占空比。然而,在 PFC 冷启动瞬间,母线电容电压极低,理论前馈占空比会非常大。为了保证启动过程中电感电流不发生严重的过冲,必须人为压制并缓慢地释放这个控制前馈量。
软件巧妙地引入了前馈乘数系数 Feed.ssK,该系数在 PFC 启动过程中由 0 缓慢增加到 1 (Q15的 32767),保证输出给硬件的前馈占空比呈爬坡式缓慢增加。
1 | /* |
电流参考值软启 (Irefss)
同理,为了保证电流闭环控制在 PFC 启动过程中不引发严重过流,系统对生成目标正弦波形指令的核心变量——电流参考值也引入了软启动缩放系数 Iac.RefssK。该系数在启动过程中同样由零开始缓慢上升,确保闭环给出的电流指令像拉橡皮筋一样平滑过渡。
1 | /* |
PFC状态机程序
200Hz 系统中低频中断事件与 PFC 运行状态机
在数字电源控制系统中,不同优先级的任务需要分配到不同频率的中断中执行。前述章节中,微秒级的电流环放置在最高频的 ADC 中断中,毫秒级的电压环放置在 1kHz 中断中;而对于系统宏观的运行状态调度(如开机自检、继电器吸合、软启动爬坡、故障恢复等)以及与上位机的通信任务,则不需要极高的刷新率。
因此,系统专门设立了一个 200Hz(即 5ms 周期)的低频中断来统筹管理 PFC 的全局状态机(State Machine)。本章将详细解析这一核心状态机的流转机制与底层 C 语言实现。
200Hz 中断事件概述
200Hz 硬件中断由内部定时器 Timer1 触发,其中断优先级配置为 Level3,在运行过程中可以被优先级更高的 ADC 快速中断与 1kHz 环路中断嵌套打断并运行。
这种嵌套中断架构保证了底层高频发波的绝对实时性,同时又让 CPU 能在空闲切片时间内有条不紊地处理系统状态机调度、输入电压宏观保护与外部 SCI 串口通信任务。
其 200Hz 中断服务程序的整体执行流程图如下:
中断入口核心代码精析
1 |
|
PFC 运行状态机架构设计
系统软件采用标准的有限状态机(FSM)架构来标定和管理模块的每一个运行节点。程序状态机运行周期为严格的 5ms,整体生命周期被划分为五大核心状态:初始化状态(Init)、空闲等待状态(Wait)、软启动状态(Rise)、正常运行状态(Run)以及故障保护状态(Err)。
定义状态机的 C 语言枚举量如下:
1 | // 状态机枚举量定义 |
各个状态之间的安全跳转条件与拓扑关系如下图所示:
严格的状态跳转条件定义如下:
- 初始化状态至空闲状态:上电完成程序参数初始化,并且在底层完成电流硬件零点偏置采样后,跳转至等待状态。
- 空闲状态至软启动状态:等待 BUS 母线电容通过防浪涌电阻自然充电接近稳定极值,闭合主功率继电器后跳转至软起动状态。
- 软启动状态至正常运行状态:正式开启 PWM 发波,随着参考电流软起、前馈软起结束且输出电压达标后,切入运行态。
- 软启动状态至故障状态:在启动爬坡过程中若发生任何越限故障或触发保护,立即打断并跳入故障态。
- 正常运行状态至故障状态:稳态正常运行过程中检测到电网或负载发生致命故障或保护动作。
- 故障状态至空闲状态:故障根源消除且经过安全延时后自动跳转,模块执行自动恢复重新启动流程。
由 5ms 周期调度的状态机主函数结构极其精简清晰:
1 | /** =================================================================== |
初始化状态 (StateMInit) 与电流偏置采样
模块初上电或发生硬件复位后,程序首当其冲进入初始化状态。在此状态下,CPU 将完成程序运行相关参数的初始化配置,包含 PFC 控制变量初始化、环路变量初始化、SCI 通信配置以及极其关键的电流采样硬件零偏计算,同时对过流过压历史标志位进行清零。
由于运算放大器在实际电路中存在固有的温漂和零点电压偏置,在未发波(无电流)状态下,必须先读取 256 次 ADC 采样值求平均,将其作为后续运算的“绝对物理零点”,以此消除硬件误差。
当电流偏置采样完成后,程序完成初始化,状态机才会正式放行,进入空闲等待状态(Wait/Idle)。
其电流偏置采样的流程图如下:
代码精析:初始化与零偏提取
1 | /** =================================================================== |
空闲等待状态 (StateMWait) 与继电器控制
当初始化结束后,程序进入空闲(等待)状态。此时电源已接入电网,交流电通过防浪涌 NTC/PTC 电阻和整流桥向巨大的直流母线电容进行自然充电。
在此状态下,程序将:清软启动标志位准备后续软启,强制保持 PWM 关机状态,初始化电压环参考值与控制量。
核心判断逻辑为:通过侦测 BUS 母线电压的微分变化率来判断电容是否充满。当检测到 BUS 电压变化极小(两次检测相差不超过 10V)时,说明母线电容的自然整流预充电已接近稳定极值。
此时启动 BUS 电容自然整流充电保持计时器,若保持 500MS 电压均未快速增长,可笃定 BUS 电容已完全充满电。此时系统将下发指令闭合主继电器(短路掉防浪涌电阻),随后状态机跳转至正式的等待软启状态。
空闲状态保护继电器免受大电流电弧烧结的流程逻辑如下:
代码精析:电压微分侦测与继电器驱动
1 | /** =================================================================== |
闭环软启动爬坡状态 (StateMRise)
继电器吸合后,防浪涌电阻被切除,此时程序进入软启动状态机(Rise)。为了防止直接将目标电压设定为 380V 导致环路瞬间输出满载占空比炸管,必须让目标参考指令“温柔地长起来”。
环路控制量将在此进行最后一次初始化复位并正式开启 PWM 发波。系统巧妙地将初始电压参考量设定为当前实际采样到的自然 BUS 电压,随后在一个渐进的过程中让该参考电压递增爬坡至 380V。当参考电压达到目标设定电压,且实际反馈的 bus 电压也成功追随至目标电压的安全余量范围内时,判定起机成功。
此时,状态机平稳切换进入正常运行状态,PFC_OK 硬件信号拉高通知后级用电,软启结束标志位彻底置位。
软启动爬坡阶段的严谨流程图如下:
代码精析:无缝衔接的软起动控制
1 | /* |
正常运行状态 (StateMRun) 与 故障状态 (StateMErr)
稳态运行 (StateMRun)
PFC 系统的稳态运行完全依赖于底层毫秒/微秒级硬件中断中的闭环矩阵运算。在正常运行状态(Run)的 200Hz 状态机分支中,主调度器事实上并不需要进行任何显式的干预与处理。
因此,StateMRun 函数内部为空,仅作为状态保持锚点存在。
1 | /* |
故障保护状态 (StateMErr)
电源系统面临的环境复杂恶劣,一旦检测到底层抛出硬件过流、软件过压、过热等越限错误,主状态机将毫无延迟地被强行切入故障状态(Err)。
在故障态下,首要任务是保命:立即清零 PFC 关机发波标志位(切断硬件驱动)、清零所有软启标志位、强行拉低关闭 PFC_OK 信号以掐断后级吸电,并彻底复位所有环路计算参数防止积分器在死锁期内疯狂累积导致爆表。
当引发保护的物理故障信息完全清除(如温度下降、浪涌消失等)后,程序将执行严谨的恢复出厂机制。需要特别注意的一个物理陷阱是:当 PFC 强制关闭后,母线电压会因为无法补充能量而自然跌落至网侧整流电压,这会必然诱发次生的“母线欠压保护(UVP)”。因此,在主状态机跳转回空闲状态(Wait)恢复重启动之前,必须预先人为介入,强行抹除因停机带来的虚假母线欠压保护故障标志位,最后重置控制变量以准备全新的生命周期。
故障发生与自愈流转逻辑如下:
1 | /* |
输入过压欠压保护
交流输入过压与欠压保护及滞环逻辑设计
在数字 PFC 电源系统的实际工业运行中,交流电网(AC Grid)的电能质量往往难以保证,随时可能出现电压骤升(浪涌过压)或骤降(跌落欠压)。如果 PFC 控制器在极端恶劣的电网条件下依然强行全功率工作,极易导致占空比饱和、主电感过流饱和,最终引发炸机等毁灭性硬件故障。
因此,系统在 200Hz 的状态机调度中断中,专门设置了输入电压检测与保护模块(VacCheck)。本章将详细解析输入欠压与过压的数字定标推导、保护触发逻辑,并着重讲解电源控制中极为核心的安全概念——滞环(Hysteresis)机制。
核心概念深度解析:什么是“滞环”保护?
在电源保护逻辑中,滞环控制(Hysteresis Control)是一项不可或缺的设计哲学。
滞环的物理定义:
简单来说,滞环就是让“触发保护动作的门限”和“解除保护恢复工作的门限”不在同一个数值上,两者之间人为地拉开一个安全距离(被称为“死区”)。发生输入欠压保护和输入过压保护均具备滞环恢复的能力。
为什么必须要有滞环?(避免临界高频震荡)
假设系统设定交流过压保护点为 253V,如果不加滞环(即恢复开机点也是 253V):
当电网电压刚好在 253V 附近伴随电网杂波发生微小波动时(例如在 253.1V 与 252.9V 之间跳动),控制系统就会在极短的时间内疯狂地在“保护关机”和“恢复开机”之间来回切换。这种高频的启停震荡会产生极其恶劣的瞬态浪涌电流,瞬间击穿功率管。
引入滞环后的完美解决:
我们在系统里人为设定一个 15V 的滞环电压。
- 过压触发点:253V
- 过压恢复点:253V - 15V = 238V
当电压飙升越过 253V 触发停机后,哪怕电压立刻跌回 252V,系统也绝对不会恢复工作。必须等到电网电压彻底跌落并稳稳降至 238V 的安全线以下,系统才会解除过压警报。这就如同一道宽阔的护城河,彻底扼杀了临界点频繁启停震荡的隐患。
保护阈值物理量与 DSP 数字标幺换算
为了在 DSP 单片机中高效且精准地执行电压判定,我们需要将上述包含滞环的物理电压门限,严谨地映射转换为 Q15 格式的标幺化纯数字量。
定义交流电网的保护滞环电压偏移量为 15V:
1. 输入过压保护(OVP)对应的数字量:
根据系统标称的最高允许输入有效值 $V_{acmax}$,换算进入 DSP 的标幺门限:
2. 输入过压保护恢复对应的数字量:
触发过压后,必须减去滞环电压,才能进入恢复判定区间:
3. 输入欠压保护(UVP)对应的数字量:
根据系统标称的最低允许输入有效值 $V_{acmin}$,换算欠压停机门限:
4. 输入欠压保护恢复对应的数字量:
触发欠压后,电网电压必须回升加上滞环电压,才能确认电网已恢复可靠供电能力:
通过严密的数学计算,我们得到了 $16943$、$15939$、$12523$、$13528$ 这四个极为关键的定点数字。它们将直接以宏定义的形式固化在 C 语言代码中,充当安全守门员。
程序判定流程与 C 语言核心实现
系统的电压安全调度策略与流程执行如下:
- 当检测电压有效值小于阈值,则触发输入欠压保护故障,置位输入欠压保护故障标志位,PFC关机标志位清零,关闭PFC_OK信号,跳转故障状态。
- 当检测电压有效值大于阈值,则触发输入过压保护故障,置位输入过压保护故障标志位,PFC关机标志位清零,关闭PFC_OK信号,跳转故障状态。
- 当发生输入欠压保护或输入过压保护后,若检测电压有效值均在合理范围内,则清过压和欠压故障标志位,等待状态机跳转空闲状态重启(无其他故障)。
其严密的程序流转判断逻辑如下图所示:
核心代码逐行深度精析
下面的代码完全映射了我们推导的四个数字标幺量,并使用按位操作(Bitwise Operations)安全地管理系统状态。
1 | /* |



























































