handle_priority.c
源文件路径:
logic/handle_priority.c所属模块:logic(能量调度核心) 代码行数:206
1. 文件职责
本文件实现「光伏优先(PV priority)」AC 控模式下总功率目标值的下发动作函数集合,是 PV_PRIORITY_AC_CONTORL_STATE 状态机的执行层(状态判断在上层、功率赋值在本文件)。文件头注释说明它是因为 DC 控 / AC 控条件编译的需要,从 logic/ac_control.c 中拆分出来的。它只写入 g_t_logic_info 里 AC 侧的总设值(s32_ac_total_set_inv_power、s32_ac_total_set_bat_charge_limit_power、s32_ac_total_set_bat_discharge_limit_power、u8_ac_total_set_bat_forced_charge_en),不做逆变器/电池的直接硬件操作。驱动方有两个:logic/logic.c 的 ac_control_total_power_photovoltaic_priority_calculate()(光伏优先状态机,软定时限制调整速率)与 logic/ac_control.c 的 fsm_total_power_ac_control()(自发自用状态机,INV_AC_CTRL 条件编译内)。数据流位置:电表/逆变器采样 → t_logic_control_parameter → 本文件的反馈闭环计算 → s32_ac_total_set_* → 上层限幅与逆变器下发。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
PV_PRIORITY_AC_CONTORL_STATE | 枚举(定义于 handle_priority.h) | 光伏优先 AC 控状态机的 6 个状态:PRIORITY_DEFAULT_STATE=0、PRIORITY_GRID_TRACK_BACKUP_BELOW_PV_STATE=1、PRIORITY_GRID_TRACK_BACKUP_OVER_PV_STATE=2、PRIORITY_GRID_TRACK_WITHOUT_PV_STATE=3、PRIORITY_GRID_ZERO_WITHOUT_PV_STATE=4、PRIORITY_BAT_OPEN_WITH_PV_STATE=5 |
g_t_logic_info | 全局结构体(logic.h) | 本文件唯一读写对象,含 t_config_data / t_logic_control_parameter / AC 总设值三组字段 |
g_t_logic_info.s32_ac_total_set_inv_power | s32 | AC 侧逆变(电表侧)功率总设值,本文件核心输出量,单位为 W |
g_t_logic_info.s32_ac_total_set_bat_charge_limit_power | s32 | 电池充电功率上限,写入后被 logic_charge_dischg_power_limit() 等消费 |
g_t_logic_info.s32_ac_total_set_bat_discharge_limit_power | s32 | 电池放电功率上限 |
g_t_logic_info.u8_ac_total_set_bat_forced_charge_en | u8 | 强制充电使能,本文件各状态一律写 FALSE |
TRUE / FALSE | 宏 | 定义于公共头文件,取值为 1 / 0(本文件仅用于给 u8_ac_total_set_bat_forced_charge_en 赋 FALSE) |
OSTimeGet | uCOS-II API 间接相关 | 本文件自身未调用;调用方 logic.c 用 OSTimeGet() + u32_calculation_interval 作为软定时门控 |
本文件没有定义结构体、联合体或位域,也没有自定义宏常量(阈值全部以字面量出现在表达式中)。
3. 函数清单
| 函数名 | 作用域 | 说明 |
|---|---|---|
total_power_control_grid_track_calculate | 全局(函数头注释误写为 static) | 有 PV 追踪电表归零:置满充/放限值,并按电表功率做 PI 增量闭环 |
total_power_control_grid_zero_without_pv_calculate | 全局(函数头注释误写为 static) | 无 PV 且电表已归零时的处理,含 s_u8_cnt 去抖与防小电流放电逻辑 |
handle_priority_default_state | 全局 | 默认态:不做电池限值,仅按馈网上限跟踪逆变功率 |
handle_priority_grid_track_backup_below_pv_state | 全局 | 低于 PV 的馈网跟踪备份态:允许充电、禁止放电 |
handle_priority_grid_track_backup_over_pv_state | 全局 | 高于 PV 的馈网跟踪备份态:按电表增量给放电限值、禁止充电 |
handle_priority_grid_track_without_pv_state | 全局 | 无 PV 追踪态,直接转调 total_power_control_grid_track_calculate() |
handle_priority_grid_zero_without_pv_state | 全局 | 无 PV 归零态,直接转调 total_power_control_grid_zero_without_pv_calculate() |
共 7 个函数,全部为文件级非 static 定义(尽管注释块里写着 static)。
4. 核心逻辑解析
4.1 状态机与驱动时序
状态迁移条件不在本文件,而在 logic/logic.c 的 pp_total_power_ac_control_state_handle() 内,本文件只负责「进入某状态后如何算功率」。迁移判定依据(t_logic_control_parameter):
| 当前输入 | 迁移结果 | ||||
|---|---|---|---|---|---|
u8_pv_status == FALSE 且 (s32_pgrid_metert < -50 或 s32_pgrid_metert > s32_system_self_consumption) | PRIORITY_GRID_TRACK_WITHOUT_PV_STATE | ||||
u8_pv_status == FALSE 且电表在 ±区间内 | PRIORITY_GRID_ZERO_WITHOUT_PV_STATE | ||||
u8_pv_status == TRUE、u8_bat_status == FALSE | PRIORITY_BAT_OPEN_WITH_PV_STATE | ||||
PV 有效、电池有效、s32_pgrid_metert < -50(馈网中),且 `\ | \ | s32_pgrid_metert\ | \ | 落在 s32_max_feedin_power ± 200 内,或逆变已接近满载(s32_pinvt > s32_inv_rated_output_power - 100`) | PRIORITY_GRID_TRACK_BACKUP_BELOW_PV_STATE |
| PV 有效、电池有效、馈网中但既不贴近馈网上限也不满载 | PRIORITY_DEFAULT_STATE | ||||
PV 有效、电池有效、s32_pgrid_metert > s32_system_self_consumption(取电超过自耗) | PRIORITY_GRID_TRACK_BACKUP_OVER_PV_STATE | ||||
| 其余 | PRIORITY_DEFAULT_STATE |
驱动时序:ac_control_total_power_photovoltaic_priority_calculate() 每次先用 OSTimeGet() 与 u32_calculation_ac_total_inv_tick / u32_calculation_interval 做软定时门控(未到间隔直接 return),然后「先判状态、再执行动作」(pp_total_power_ac_control() 的 switch)。整个调用链在 task_system_logic_control 任务中周期执行(该任务同时被 g_t_fast_dispatch_flag 事件标志触发快调度)。
4.2 关键算法与公式
(1)馈网跟踪的增量闭环(total_power_control_grid_track_calculate、handle_priority_grid_track_backup_below_pv_state、handle_priority_grid_track_backup_over_pv_state 三处完全相同的代码):
s32_ac_total_set_inv_power += s32_pgrid_metert / u8_regulator_speed;
s32_pgrid_metert 为正表示电表侧取电、为负表示馈网。取电时增大逆变目标功率以抵消,馈网时减小。这是一个纯增量(积分型)调节器,u8_regulator_speed(取值 1~5,由 get_inv_regulator_speed() 按机型/电网功率给出)是调节步长分母,值越大调节越慢。
(2)大偏差直接前馈 + 小偏差增量微调(handle_priority_default_state 等):
if (abs(s32_max_feedin_power + s32_pgrid_metert) > 100)
s32_ac_total_set_inv_power = s32_max_feedin_power + s32_pgrid_metert + s32_pinvt;
else
s32_ac_total_set_inv_power += (s32_max_feedin_power + s32_pgrid_metert) / u8_regulator_speed;
即:当「馈网上限 + 实际电表功率」的绝对值超过 100 W 时,用前馈方式一步把目标拉到 max_feedin + pgrid_metert + pinvt;进入 ±100 的死区后改用增量微调,避免在设定点附近来回过冲。
(3)无 PV 归零态的三段判断(total_power_control_grid_zero_without_pv_calculate,含 static u8 s_u8_cnt 去抖):
| 条件 | 动作 |
|---|---|
abs(s32_pinvt) < s32_system_self_consumption | s_u8_cnt = 0;s32_ac_total_set_inv_power = 20;充、放限值均置 0(禁充禁放,避免电池小电流放电) |
abs(s32_pinvt) < 140 && abs(s32_pgrid_metert) < 10 | s_u8_cnt = 0;s32_ac_total_set_inv_power = 40;充、放限值均置 0(逆变不封波空载场景) |
| 其余 | s_u8_cnt++,仅当 s_u8_cnt > 2 才:inv_power += pgrid_metert / regulator_speed,并把充/放限值恢复为配置的满值 |
第三段连续 3 次(受计算间隔门控,实际约 3 个调度周期)才动作,起的是「确认进入稳态再恢复电池能力」的去抖作用。
(4)各状态的电池限值:
| 状态 | 充电限值 | 放电限值 |
|---|---|---|
PRIORITY_DEFAULT_STATE | 0 | 0(第 105-106 行先置 0) |
..._BACKUP_BELOW_PV_STATE | s32_bat_charge_power_limit(满) | 0 |
..._BACKUP_OVER_PV_STATE | 0 | s32_pgrid_metert / u8_regulator_speed(增量值) |
..._GRID_TRACK_WITHOUT_PV_STATE | s32_bat_charge_power_limit | s32_bat_dischg_power_limit |
..._GRID_ZERO_WITHOUT_PV_STATE | 前两段 0、第三段满值 | 前两段 0、第三段满值 |
handle_priority_default_state / ..._below_pv_state / ..._over_pv_state 三者在结尾都有统一的负值保护:
if (g_t_logic_info.s32_ac_total_set_inv_power < 0) g_t_logic_info.s32_ac_total_set_inv_power = 0;
4.3 通信协议帧格式
本文件不涉及任何通信收发,无帧格式、校验、超时重试逻辑(属 net/、midware/ 模块)。
4.4 与 uCOS-II 的配合
本文件不直接调用任何 uCOS-II API,不使用信号量/消息邮箱。它运行在 task_system_logic_control 任务上下文内,被事件标志 g_t_fast_dispatch_flag(POST_PEND_FAST_ENABLE)加速;跨任务同步由调用方通过 g_t_logic_info 结构体字段的「写—读」隐式完成,本文件自身无临界区保护。
4.5 关键全局变量读写
| 变量 | 读/写 | 触发条件 |
|---|---|---|
s32_ac_total_set_inv_power | 读+写 | 5 个状态处理函数都会写;default/below/over 为「大偏差赋值、小偏差累加」两种语义 |
s32_ac_total_set_bat_charge_limit_power | 写 | 状态相关,见 4.2 表 |
s32_ac_total_set_bat_discharge_limit_power | 写 | 状态相关,见 4.2 表 |
u8_ac_total_set_bat_forced_charge_en | 写 | 每个状态处理入口都无条件写 FALSE |
t_logic_control_parameter.s32_pgrid_metert | 读 | 闭环输入,电表总相功率 |
t_logic_control_parameter.s32_pinvt | 读 | 逆变侧总功率 |
t_logic_control_parameter.s32_max_feedin_power | 读 | 系统最大允许馈网功率 |
t_logic_control_parameter.s32_system_self_consumption | 读 | 系统自耗阈值 |
t_logic_control_parameter.u8_regulator_speed | 读 | 调节步长(1~5),所有除法分母 |
t_logic_control_parameter.s32_bat_charge_power_limit / s32_bat_dischg_power_limit | 读 | 满充/满放限值来源 |
5. 对外接口
导出(供外部调用)——均通过 handle_priority.h 声明:
| 名称 | 调用者 |
|---|---|
handle_priority_default_state() | logic/logic.c:1947、logic.c:1968(switch 的 default 分支) |
handle_priority_grid_track_backup_below_pv_state() | logic/logic.c:1951 |
handle_priority_grid_track_backup_over_pv_state() | logic/logic.c:1955 |
handle_priority_grid_track_without_pv_state() | logic/logic.c:1959 |
handle_priority_grid_zero_without_pv_state() | logic/logic.c:1963 |
total_power_control_grid_track_calculate() | logic/ac_control.c:1022(fsm_total_power_ac_control,覆盖 GRID_TRACK_WITH_PV_STATE / GRID_TRACK_WITHOUT_PV_STATE / GRID_ZERO_WITH_PV_STATE 三个自发自用状态)、本文件 191 行 |
total_power_control_grid_zero_without_pv_calculate() | logic/ac_control.c:1030(GRID_ZERO_WITHOUT_PV_STATE)、本文件 203 行 |
PV_PRIORITY_AC_CONTORL_STATE 枚举类型 | logic/logic.c(状态变量 s_u32_prestate、l_u32_nextstate) |
本文件不导出任何全局变量(全部输出都通过 g_t_logic_info 生效)。
被调用(外部依赖):
| 名称 | 来源 |
|---|---|
abs() | C 标准库 stdlib.h(经 includes.h → logic.h 引入) |
g_t_logic_info(含 t_logic_control_parameter、t_config_data) | logic/logic.c 定义,logic.h 声明 |
FALSE | 公共类型/宏头文件(includes.h 链) |
6. 依赖关系
依赖:
logic/logic.h(#include "logic.h")——提供g_t_logic_info、t_logic_control_parameter、FALSE、abs()链条;logic/handle_priority.h(#include "handle_priority.h")——PV_PRIORITY_AC_CONTORL_STATE与自身原型的声明;- 间接依赖
system/sys/chip.h(handle_priority.h内#include "chip.h")。
被依赖:
logic/logic.c——状态机迁移判定 +pp_total_power_ac_control()分发;logic/ac_control.c——自发自用状态机复用其中两个计算函数;logic/handle_priority.h被ac_control.c、logic.c、handle_priority.c三处 include。
7. 备注与风险点
- 函数头注释与实际定义不符:20 行、36 行的注释写
@Name :static void total_power_control_grid_track_calculate(),但 26 行/42 行的真实定义没有static;同理其余 5 个函数头都挂着错误的@Name(例如 114 行的函数名叫handle_priority_grid_track_with_pv_state、147/182/194 行的注释全部重复成..._backup_over_pv_state)。这些是复制粘贴遗留,容易误导调用者,建议同步修正。 - 大量重复代码:
handle_priority_default_state、..._below_pv_state、..._over_pv_state三个函数里「前馈 + 增量」的逆变功率计算块字节级相同(仅电池限值不同),是典型的三份拷贝,后续修改极易漏改其中一份。 PRIORITY_BAT_OPEN_WITH_PV_STATE没有对应处理函数:logic.c的pp_total_power_ac_control()没有该 case,会落到default分支静默执行handle_priority_default_state()。也就是说「PV 有效但电池未使能」这一状态在光伏优先路径下与默认态行为完全相同,与该状态的语义可能不一致(自发自用路径ac_control.c里有独立的BAT_OPEN_WITH_PV_STATE/total_power_control_bat_open_with_pv_calculate()处理)。switch的default里只有一句// TODO:报错信息,无任何告警上报。- 除法无零保护:4 处
s32_pgrid_metert / u8_regulator_speed与 2 处(max_feedin + pgrid_metert) / u8_regulator_speed都直接以配置量为分母。当前get_inv_regulator_speed()(inverter.c:2634)的默认值是REGULATOR_SPEED_5且所有分支都赋 1~5,不会为 0;但该值来自运行期机型判断,一旦被外部或未覆盖分支写成 0 就会触发除零(GD32F407 上为硬件异常)。 - 整数除法截断与闭环死区:
pgrid_metert / regulator_speed在|pgrid_metert| < regulator_speed(即 <5 W)时结果为 0,目标功率会「卡死」不再调整;负值除法向零取整(C99),在馈网方向与取电方向的步长不对称。 - 累积量无上限:
s32_ac_total_set_inv_power += ...是累加写,只有< 0的下限钳位,没有上限钳位。若上层限幅函数(logic_charge_dischg_power_limit())不兜底,持续同向偏差会让该值单向爬升到s32饱和。相对地,前馈分支是直接赋值、不累加,两种语义混在同一变量上。 - 魔法数字:
100(死区/阈值 W)、-50(判定馈网的功率门限)、200(馈网上限允许偏差)、20/40(归零态固定逆变设值)、140(逆变功率门限)、10(电表功率门限)、> 2(去抖次数)、s32_inv_rated_output_power - 100。这些既无宏、也无注释说明量纲(推断为 W),建议提取为具名常量。 - 去抖计数期间限值保持旧值:
total_power_control_grid_zero_without_pv_calculate()的第三段在s_u8_cnt <= 2时既不写充电限值也不写放电限值,而是保留上一状态遗留在g_t_logic_info中的值。若上一状态是放电(如..._over_pv_state刚写过放电限值),这 3 个周期内电池仍沿用旧限值,属于状态切换瞬态的未定义行为。 - 注释与实现不一致:第 65 行注释写「电池放电满足电表归零」,但该分支实际把充电限值也恢复成了满值
s32_bat_charge_power_limit;第 157 行注释掉的s32_ac_total_set_bat_charge_limit_power = 0;在 174 行又原样出现;第 158 行先把放电限值置 0,第 173 行又立刻覆盖,属冗余赋值。 - 跨任务可见性:本文件写的
g_t_logic_info字段被其他任务(逆变器下发、并机、云端上报)读取,而写入过程(例如 4 个字段的非原子赋值序列)没有关中断/临界区保护。若读方在写入中途取值,会看到「电压目标已更新但电池限值还是上一状态」的混合状态。