key.h
LOGIN_IN_T 的生命周期5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
hmi/key.h所属模块:hmi(人机界面) 代码行数:248
1. 文件职责
key.h 是 HMI 按键/登录模块的对外契约头文件,只做三件事:定义身份与显示类型的枚举、定义登录有效期结构体 LOGIN_IN_T、以及用大量 *_MAX/*_MIN/*_DEFAULT 宏集中声明"界面上可编辑参数的取值范围"。
它处在配置写入链的最前端:hmi/key.c 的所有数值编辑都从本文件取上下限(例如 Button_Handle(..., GRID_VAC_VOLT_MAX, GRID_VAC_VOLT_MIN)),因此本文件实际上承担了"设置页参数合法性第一道闸门"的角色——改这里的宏就会改变现场可调范围。
同时它把三个密码常量(用户/管理员/安装商)定义在这里,hmi/key.c 的认证状态机与 data/system_config/system_config.c:106,1160 的出厂初值都引用它们,是密码策略的唯一常量源。
本文件不定义任何函数、不定义任何变量(只有两个 extern 声明),本身不含逻辑,由 hmi/key.c 单向包含。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
DEBUG_HMI | 宏 = 0(hmi/key.h:15) | HMI 任务运行计数调试开关;hmi/key.c:8981 用它决定是否累加 g_t_task_run_status.u32_task_hmi_cnt |
PLUS / SUB | 宏 = 0 / 1(:17-18) | 传给 Button_Handle() 的加/减方向标志,取代裸 0/1 |
USER_PASSWORD | 宏 = 1234(:20) | 用户密码出厂值;运行期为 g_t_system_base_info.u16_user_password(system_config.c:106 用它初始化) |
ADMIN_PASSWORD | 宏 = 1397570(:21) | 管理员 7 位密码;hmi/key.c 以 ADMIN_PASSWORD / 10000(139,输入为 0139)和 ADMIN_PASSWORD % 10000(7570)分两次校验 |
INSTALLER_PASSWORD | 宏 = 1111(:22) | 安装商密码;system_config.c:1160 用它把"被改成安装商密码的用户密码"复位为 USER_PASSWORD |
POWER_FACTORY_MODE_OFF…POWER_FACTORY_MODE_PF_P_CURVE | 宏 = 0…6(:25-31) | 无功/功率因数响应模式:0 关闭、1 PF 过励、2 PF 欠励、3 Q 过励、4 Q 欠励、5 Q-U 曲线、6 PF-P 曲线;被 hmi/key.c:2806-:2839 的模式轮转与 hmi/ui/ui_control_exception.c:87 的复位逻辑引用 |
GRID_VAC_VOLT_MAX/MIN | 宏 = 3000 / 1400(:34-35) | 电网电压保护点范围(0.1 V,即 300.0 V / 140.0 V) |
GRID_FAC_FREQ_MAX/MIN | 宏 = 5500 / 4500(:37-38) | 电网频率保护点范围(0.01 Hz,即 55.00 / 45.00 Hz) |
GRID_TIME_VAC_MAX/MIN | 宏 = 65535 / 0(:40-41) | 电压保护动作时间范围(ms) |
GRID_TIME_FAC_MAX/MIN | 宏 = 65535 / 0(:43-44) | 频率保护动作时间范围(ms) |
GRID_TIME_PRO_TH_MAX/MIN | 宏 = 65535 / 0(:46-47) | 保护阈值类时间(并网等待、重连延时、GFCI 阈值)范围 |
GRID_OVER_FREQ_START_MAX/MIN | 宏 = 5050 / 5020(:49-50) | AS4777 过频降载起始点范围 |
GRID_OVER_FREQ_STOP_MAX/MIN | 宏 = 5200 / 5100(:52-53) | 过频降载终止点范围 |
GRID_UNDER_FREQ_START_MAX/MIN | 宏 = 4990 / 4900(:55-56) | 欠频降载起始点范围 |
GRID_UNDER_FREQ_STOP_MAX/MIN | 宏 = 4900 / 4700(:58-59) | 欠频降载终止点范围 |
GRID_FREQ_DROOPRATE_MAX/MIN | 宏 = 12 / 2(:61-62) | 频率下垂率范围(全工程无引用,死宏) |
GRID_OF_REDUCE_POWER_DELAY_TIME_MAX/MIN | 宏 = 1000 / 0(:64-65) | 过频降功率延时范围(全工程无引用,死宏) |
PF_LOCK_OUT_POINT_MAX/MIN、PF_LOCK_IN_POINT_MAX/MIN | 宏 = 98/90、10/5(:67-70) | PF 曲线锁定/解锁点范围 |
PU_POWER_LOWER_LIMIT_MAX/MIN | 宏 = 100 / 0(:72-73) | P-U 曲线发电下限百分比 |
PU_CHARGE_POWER_UPPER_LIMIT_MAX/MIN | 宏 = 2300 / 2160(:75-76) | P-U 曲线充电上限(1.1 p.u. = 253 V 附近) |
PU_VOLTAGE1..4_MAX/MIN | 宏(:78-88) | P-U 曲线 4 个拐点电压:2000/2100、2160/2300、2400/2550、2530/2650 |
QU_UNDER_EXCITED_VAR_MAX/MIN、QU_OVER_EXCITED_VAR_MAX/MIN | 宏 = 100/0(:90-:94) | Q-U 曲线欠励/过励无功百分比 |
QU_COMPAREVOLT_V1..V4_MAX/MIN | 宏(:96-:106) | Q-U 曲线 4 个比较电压,范围与 PU_VOLTAGE 相同 |
TN_TO_WGRA_UP_MAX/MIN、TN_TO_WGRA_DOWN_MAX/MIN | 宏 = 1200 / 0(:108-112) | 功率变化率 Tn→Wgra 上升/下降时间(ms) |
REACTIVE_POWER_POINT_MAX/MIN | 宏 = 80 / 0(:114-115) | DRM 无功设定点百分比 |
PF_VALUE_OVER_EXCITED_MAX/MIN、PF_VALUE_UNDER_EXCITED_MAX/MIN | 宏 = 100/90(:117-:121) | 非 AS4777 安规下的 PF 设定值范围 |
PF_VALUE_OVER_EXCITED_AS4777_MAX/MIN、PF_VALUE_UNDER_EXCITED_AS4777_MAX/MIN | 宏 = 100/80(:123-:127) | AS4777 安规下的 PF 设定值范围(下限放宽到 80) |
Q_VALUE_MAX/MIN | 宏 = 2760 / 0(:129-:130) | Q 模式无功设定值范围(0.01 kVar 量级) |
QU_VOLT_UP_MAX/MIN、QU_VOLT_LOW_MAX/MIN | 宏 = 110/100、100/90(:132-:136) | Q-U 曲线电压上/下限百分比 |
CURVE_UPPER_LIMIT_MAX/MIN、CURVE_LOW_LIMIT_MAX/MIN | 宏 = 100/90(:138-:142) | PF-P 曲线功率上/下限百分比 |
CURVE_POWER_UPPER_MAX/MIN、CURVE_POWER_LOWER_MAX/MIN | 宏 = 100/0(:144-:148) | PF-P 曲线功率上下限 |
INVERTER_POWER_PERCENT_LIMIT_MAX/MIN | 宏 = 100 / 0(:150-151) | 逆变器功率百分比限制(全工程无引用,死宏) |
PV_CAPACITY_MAX/MIN/DEFAULT | 宏 = 99999/0/0(:153-155) | 储能侧 PV 装机容量范围与越界回落值 |
PV_CAPACITY_GRID_MAX/MIN/DEFAULT | 宏 = 99999/0/0(:157-:159) | 并网侧 PV 装机容量范围与越界回落值 |
CURRENT_LIMIT_MAX/MIN/DEFAULT | 宏 = 99999/0/16(:161-:163) | 并网功率限制电流范围(A),缺省 16 A |
USER_FORCE_CHARGE_CUT_SOC_MAX/MIN/DEFAULT | 宏 = 100/0/100(:165-:167) | 用户一键强充截止 SOC |
GENERATOR_RATE_POWER_LIMIT_MAX/MIN | 宏 = 99999 / 0(:169-:170) | 油机额定功率范围(W) |
GENERATOR_RATE_PERCENT_LIMIT_MAX/MIN | 宏 = 100 / 0(:171-:172) | 油机降额百分比 |
GENERATOR_SOC_LIMIT_MAX/MIN | 宏 = 100 / 0(:173-:174) | 油机 SOC 起停阈值 |
GENERATOR_TIME_LIMIT_MAX/MIN | 宏 = 24 / 0(:175-:176) | 油机 TOU 起止小时 |
GENERATOR_CHARGE_POWER_LIMIT_MAX/MIN | 宏 = 99999 / 0(:177-:178) | 油机充电功率 |
CT_RATE_MAX/MIN/DEFAULT | 宏 = 999 / 1 / 1(:180-:183) | CT 变比范围(下限为 1,因为 0 会成为除数) |
DISPLAY_TYPE_E | 枚举(:186-195) | 显示外设类型:DISPLAY_NONE_E=0、DISPLAY_LCD_CHARACTER_E(LCD 字符屏)、DISPLAY_LED_LAMP_STRIP_E(四代机灯条)、DISPLAY_LED_BICOLOR_E(双色小灯板)、DISPLAY_LED_LAMP_PANEL_E(五代机亚克力灯板)、DISPLAY_LCD_PARAGRAPH_E(五代机一体机 LED 屏)、DISPLAY_LCD_RKP_E(林内项目) |
ID_E | 枚举(:198-204) | 身份等级:id_none=0、id_user、id_installer、id_admin;顺序即权限序,hmi/key.c 依赖 id_none == 0 把身份值当布尔用 |
LED_LAMP_PANE_ID_E | 枚举(:206-219) | 灯板点位索引:LED_RED、LED_BLUE、LED_DB0…LED_DB7,末尾 LED_NUM 作遍历上界 |
LOGIN_IN_T | 结构体(:221-225) | 登陆记忆:u8 id_setting_into_last(上次身份)、u32 time_setting_into_last(OSTimeGet() tick);实例为 g_t_ui_login |
3. 函数清单
本文件不定义任何函数,仅声明 9 个函数原型。下表列出全部原型及其在本工程中的真实定义位置与调用方:
| 函数名 | 作用域 | 说明 |
|---|---|---|
n_power(u8 num, u8 n) | 全局(hmi/key.h:232 声明) | 定义于 hmi/key.c:135;整数幂,仅被 hmi/key.c 内部调用 |
Key_Handle_Up(void) | 全局(:233) | 定义于 hmi/key.c:1732 |
Key_Handle_Down(void) | 全局(:234) | 定义于 hmi/key.c:4084 |
Key_Handle_Enter(void) | 全局(:235) | 定义于 hmi/key.c:6574 |
Key_Handle_Cancel(void) | 全局(:236) | 定义于 hmi/key.c:206 |
Key_Handle(void) | 全局(:237) | 定义于 hmi/key.c:8762;由 task_hmi_parse 每 10 ms 调用 |
Button_ChangeEthernetSettingLiteral(u8 *Number, u8 AddSubFlag) | 全局(:239) | 定义于 hmi/key.c:1624;IP/掩码/网关段编辑 |
Button_Get_SystemTime(void) | 全局(:240) | 本工程无对应的全局定义;同名实现是 hmi/ui/ui_setting_user_sys_date.c:11 的 static 函数,该原型为失效声明 |
Button_Handle(u32 *data, u8 bit_index, u8 flag, u32 max, u32 min) | 全局(:241) | 定义于 hmi/key.c:158;位权加减 + 上下限回绕,flag 取 PLUS/SUB |
task_hmi_parse(void *p_arg) | 全局(:243) | 定义于 hmi/key.c:8888;被 user/main.c:310 以 OSTaskCreateExt 创建 |
未在本文件声明、但在 hmi/key.c 中定义为全局函数的还有 Last_ID_Legal_Handle、Button_Get_ErrorLogInfo、Factory_Mode_Setting(三者均无非 static 的对外使用,却缺少原型);Backlight_Reload 的原型意外放在 hmi/lcd.h:430 而不是本文件。
4. 核心逻辑解析
本文件是纯声明文件,没有状态机、算法、通信帧或定时逻辑。以下说明这些声明在运行时的实际作用路径。
4.1 取值范围宏如何形成"参数合法性第一道闸门"
所有可编辑数值的边界都来自本文件,hmi/key.c 的调用模式统一为:
button_data_buf = (u32)LCD_RTDB.<字段>;
Button_Handle(&button_data_buf, <位权>, PLUS|SUB, <本文件的 MAX 宏>, <本文件的 MIN 宏>);
LCD_RTDB.<字段> = (u16|u32)button_data_buf;
分单位约定可从宏值反推(hmi/key.c 的注释与换算处佐证):
| 物理量 | 宏单位 | 证据 |
|---|---|---|
| 电压 | 0.1 V(GRID_VAC_VOLT_MAX = 3000 → 300.0 V) | hmi/key.c:1918-1922 直接下发同值 |
| 频率 | 0.01 Hz(GRID_FAC_FREQ_MAX = 5500 → 55.00 Hz) | hmi/key.c:2211-2215 |
| 时间 | ms(GRID_TIME_VAC_MAX = 65535) | hmi/key.c:1988-1992 |
| 功率限制 | 宏存 A,落盘时乘 230*3(CURRENT_LIMIT_MAX = 99999) | hmi/key.c:3097、:5543、:7870 |
| 油机时间 | 小时(GENERATOR_TIME_LIMIT_MAX = 24) | hmi/key.c:3650 |
Button_Handle() 会无条件信任这组宏,内部没有任何针对 max 的防护,所以本文件的宏值必须满足 10^bit_index < max(bit_index 由 行位数 - bCurrSubCursor 得到,见 hmi/key.c:158-197)。
4.2 密码常量如何被消费
USER_PASSWORD(1234):只在出厂初始化时用(data/system_config/system_config.c:106、:265),运行期比较对象是LCD_RTDB.wPassword(由g_t_system_base_info.u16_user_password装载,hmi/key.c:8911)。INSTALLER_PASSWORD(1111):hmi/key.c:6813直接比较;同时system_config.c:1160-1161用它做"用户密码被改成安装商密码就复位"的保护。ADMIN_PASSWORD(1397570):唯一使用"7 位拆两次输入"的密码。hmi/key.c:6808比较ADMIN_PASSWORD / 10000(139,用户需输0139,因为wDispPassword是 4 位十进制),:6765/:6735比较ADMIN_PASSWORD % 10000(7570)。中间状态由admin_password_half_right的 bit1/bit2 记录。
三个常量之间没有互相约束检查:若把 USER_PASSWORD 或 INSTALLER_PASSWORD 改成与 ADMIN_PASSWORD % 10000(7570)相同,hmi/key.c:6822-:6837 的掩码判定(0x05/0x06 分支)会导致身份判定歧义。
4.3 枚举类型的运行时用途
ID_E:hmi/key.c的identity变量、LOGIN_IN_T.id_setting_into_last、以及Key_Handle_Cancel/Up/Down/Enter里大量的if (identity == id_admin) / else if (identity == id_installer) / else if (identity == id_user)权限分派(例:hmi/key.c:354-368、:848-859、:7151-:7353)共用同一枚举,因此枚举顺序决定权限语义。DISPLAY_TYPE_E:hmi/key.c:8894读inverter_read_display_type()得到类型,只对DISPLAY_LCD_CHARACTER_E初始化 LCD/按键,并每 10 min 重新Lcd_Init();hmi/led.c:89/:285/:622按DISPLAY_LED_LAMP_PANEL_E、DISPLAY_LCD_RKP_E分流不同灯板行为。LED_LAMP_PANE_ID_E:hmi/key.c:8840-8881的led_get_bit_state()/led_hw_control()用同一点位编号索引g_t_ate_ctrol.led_lamp_pane_ctrol.bit.*与 gpio 驱动的LED_Red_ON/led_dbX_on,两边必须一一对应;:8919用LED_NUM作遍历上界。
4.4 LOGIN_IN_T 的生命周期
| 阶段 | 动作 | 位置 |
|---|---|---|
| 记录 | 密码校验成功时 set_ui_login_info(identity) 写 id_setting_into_last 与 OSTimeGet() | hmi/key.c:53-57,调用点 :6743、:6778、:6831、:6845 |
| 消费 | 主菜单进"设置"时若 is_last_id_legal() 非 0 则按记忆身份直达设置页(免密) | hmi/key.c:6597-6618 |
| 失效 | Last_ID_Legal_Handle() 在 admin/installer 超 3600000 tick(1 h)、user 超 1800000 tick(30 min)时清零 | hmi/key.c:76-93;主循环调用点 :8962 |
| 主动注销 | 设置退出页勾选"退出并注销"时 id_setting_into_last = id_none | hmi/key.c:321-:326 |
5. 对外接口
本文件导出的内容
| 类别 | 符号 | 主要使用方 |
|---|---|---|
| 类型 | LOGIN_IN_T、ID_E、DISPLAY_TYPE_E、LED_LAMP_PANE_ID_E | hmi/key.c、hmi/led.c、hmi/led/*、midware/interface/modbus/modbus.h(DISPLAY_LED_LAMP_PANE_CTROL_U 用同名点位语义) |
| 变量 | extern LOGIN_IN_T g_t_ui_login;(:228) | 仅 hmi/key.c(实测无其它引用者) |
| 变量 | extern struct RTC_DateTime SYSTEM_DATETIME;(:229) | 本工程无引用者(hmi/key.c 用的是 LCD_RTDB.LCD_DATETIME 与 Set_RTC()),属遗留声明 |
| 宏 | 三个密码常量 | hmi/key.c、data/system_config/system_config.c |
| 宏 | 全部 *_MAX/*_MIN/*_DEFAULT 编辑范围宏 | 仅 hmi/key.c(GRID_FREQ_DROOPRATE_*、GRID_OF_REDUCE_POWER_DELAY_TIME_*、INVERTER_POWER_PERCENT_LIMIT_* 三组全工程零引用) |
| 函数原型 | 9 个(见第 3 节) | hmi/key.c(全部实现)、user/main.c(仅 task_hmi_parse) |
本文件调用的外部内容
#include <includes.h>(hmi/key.h:12):这是唯一的 include。includes.h提供了u8/u16/u32基本类型(经gd32f4xx.h/chip.h)、OSTimeGet(经ucos_ii.h),并定义了Lag、SERIAL_DEBUG_LOG_OUT等宏;LOGIN_IN_T里的u32就依赖它。extern struct RTC_DateTime SYSTEM_DATETIME;依赖includes.h传递链中已可见的struct RTC_DateTime定义。- 头文件本身不引用
LCD_RTDB,但includes.h:27的#define Lag (LCD_RTDB.u8_language == English)?与English枚举(hmi/lcd.h:116)意味着任何包含key.h的翻译单元在间接包含链上会接触 LCD 类型,hmi/key.c正是靠#include "lcd.h"满足这一点。
6. 依赖关系
依赖
UCOSII/uCOS-CONFIG/includes.h(唯一直接依赖,hmi/key.h:12),并间接受gd32f4xx.h、chip.h、os_cfg.h、app_cfg.h影响。struct RTC_DateTime的定义来源(data/下的 RTC 时间结构)。
被依赖(#include "key.h" 或使用其符号)
hmi/key.c(唯一包含者,hmi/key.c:20)。data/system_config/system_config.c(使用USER_PASSWORD、INSTALLER_PASSWORD,但未#include "key.h",靠编译器的隐式可见性/其它头文件间接获得,属脆弱耦合)。hmi/ui/ui_setting_user_sys_date.c(其static Button_Get_SystemTime与key.h:240的同名原型构成命名冲突风险)。- 间接:凡包含
includes.h的翻译单元都会看到Lag宏,从而在宏展开处需要LCD_RTDB与English可见。
7. 备注与风险点
Button_Get_SystemTime是失效且冲突的原型(hmi/key.h:240):本工程只有hmi/ui/ui_setting_user_sys_date.c:11的static void Button_Get_SystemTime(void),该文件在同名签名下再加extern声明会触发链接/编译期冲突,且类型不一致时(现在恰好一致)无编译告警。建议删除。extern struct RTC_DateTime SYSTEM_DATETIME;(hmi/key.h:229)全工程无引用,是历史遗留;extern变量放在头文件里还会让每个包含者都产生一次外部引用。- 三组死宏:
GRID_FREQ_DROOPRATE_MAX/MIN(:61-62)、GRID_OF_REDUCE_POWER_DELAY_TIME_MAX/MIN(:64-65)、INVERTER_POWER_PERCENT_LIMIT_MAX/MIN(:150-151)全工程零引用,说明对应界面已被注释掉(对照hmi/key.c:649-:686、:831-:846的整段注释)。 LOGIN_IN_T的时间域是u32tick,未处理回绕:OSTimeGet()在 1000 tick/s 下约 49.7 天回绕,hmi/key.c:81/:88用OSTimeGet() - time_setting_into_last直接比较,跨回绕瞬间会得到极大差值并立即清身份(仅表现为需重新输密码,但属未处理边界)。- 密码常量互相之间无约束校验:见 4.2。若
USER_PASSWORD或INSTALLER_PASSWORD与 7570 相同,hmi/key.c:6822-:6837的0x07掩码判定会出现"用户密码对但同时被当成管理员低位"的歧义分支。 ID_E的枚举顺序有隐式语义:id_none必须为 0(hmi/key.c:339、:1469、:6597等把返回身份当布尔用);id_admin在id_user/id_installer之后但不依赖大小比较,权限判断全部是==,再加新身份时需检查所有分派点。LED_LAMP_PANE_ID_E与硬件点位的对应是"约定式"的:led_get_bit_state/led_hw_control(hmi/key.c:8840-8881)依赖枚举值 0…9 与g_t_ate_ctrol位域顺序、gpio 函数名一一对应,任一侧插值都会静默错位。- 范围宏与界面实际拆位不匹配的隐患:
GENERATOR_TIME_LIMIT_MAX = 24(2 位十进制,位权最高 10),hmi/key.c:3650用位权2 - bCurrSubCursor是对的,但:6147用3 - bCurrSubCursor会得到位权 100 > 24,触发Button_Handle的"越下限"分支直接归零。根因是本文件只提供上下限、不校验调用方传的位权。 #define DEBUG_HMI用值而非#ifdef判断:hmi/key.c:8981写#if (DEBUG_HMI == 1),所以宏必须始终有定义(当前为 0),删掉定义会退化。写法本身没问题,但注释里没有说明这一点。- 头文件缺少
extern "C"包裹:本工程为纯 C(Keil MDK + uCOS-II),当前无影响;但若将来有 C++ 测试桩会立即出问题。 - 无 include guard 命名冲突风险:
__KEY_H__(:9)属常见名,与同为__*_H__风格的其它模块头文件并存,若第三方库也定义同名宏会静默吞掉整个头文件内容(当前工程未见冲突)。