EMS 知识库
首页 / knowledge/代码解析/hmi

led.c

源文件路径:hmi/led.c 所属模块:hmi(人机界面) 代码行数:1084

1. 文件职责

本文件是 EMS 的指示灯(LED)状态机与显示驱动,负责把系统的运行状态转换成面板上各个 LED 的亮灭/闪烁。它不初始化任何硬件,只调用 hardware/gpio/gpio.c 里已经封装好的 LED_Green_ON()/led_db0_on() 之类的电平操作函数。

数据流位置:上游由 hmi/key.c 的 task_hmi_parse() 任务驱动(hmi/key.c:8896 调用 led_display_test() 做开机自检,hmi/key.c:8953 每轮循环调用 led_display()),显示类型 type 由 inverter_read_display_type()(midware/inverter/inverter.c:1776)按机型/OEM/SN 决定;下游则是 GPIO 电平与(林内项目专用)WS2812 灯带的颜色状态量 sys_current_status_color。

它的核心工作是:先统一计算 6 个"逻辑灯"状态(正常/故障/电池/电表/联网亮灭 + 联网颜色),再按 type 分支把这 6 个状态映射到 4 种物理灯板的驱动输出:字符 LCD 面板的 4 颗独立 LED、四代机长灯条(led_db0..db4)、双色小灯板(led_db0..db5)、五代机亚克力灯板(LED_Red/LED_Blue + led_db0..db7,含 5 位故障码显示与 5 段 SOC 柱)。

其中 DISPLAY_LCD_RKP_E(林内项目)分支不直接驱动 GPIO,而是计算出一个 4 值枚举写入全局 sys_current_status_color,交给新增的 WS2812 灯带模块 hmi/led/app_led.c 消费。

2. 关键数据结构与宏

本文件不定义任何结构体/枚举/宏,全部使用外部定义的类型与宏。

名称类型(结构体/枚举/宏)说明
DISPLAY_TYPE_E枚举(定义于 hmi/key.h:187-195)显示硬件类型,取值 DISPLAY_NONE_E、DISPLAY_LCD_CHARACTER_E(LCD 面板)、DISPLAY_LED_LAMP_STRIP_E(四代机灯条)、DISPLAY_LED_BICOLOR_E(双色小灯板)、DISPLAY_LED_LAMP_PANEL_E(五代机亚克力灯板)、DISPLAY_LCD_PARAGRAPH_E、DISPLAY_LCD_RKP_E(林内项目)。本文件的 type 参数即此枚举
STATUS_LED_COLOR_E枚举(定义于 hmi/led/app_led_cfg.h:48-54)长灯带系统状态色:SYS_STATUS_NOT_RUN_LED_OFF(0)/SYS_STATUS_NORMAL_LED_GREEN(1)/SYS_STATUS_FAULT_LED_RED(2)/SYS_STATUS_WARNING_LED_YELLOW(3),本文件在 RKP 分支写入 sys_current_status_color
INVERTER_TYPE / INVERTER_MAX / KELONG_TYPE / GINLONG_TYPE / SET_TYPE / ALPHAESS_TYPE / GOODWE_TYPE / INOVANCE_TYPE宏(midware/inverter/inverter.h:163-172)机型编译开关,本文件用 `#if ((INVERTER_TYPE == INVERTER_MAX) \\...)` 决定哪些灯板分支参与编译
cCheckMode/cNormalMode/cUPS宏(midware/inverter/inverter.h:22-24,值 2/3/4)逆变器运行模式,用于"正常灯""电表灯""故障灯"的判定
GRID_METER / PV_METER枚举(midware/meter/meter.h:165-166)电表站点选择,用于电表灯判定
AC_SYSTEM_MODE / HYBIRD_SYSTEM_MODE宏(logic/logic.h:22、logic/logic.h:20,值 0x01/0x03)系统模式,用于电表灯的双表判定分支
g_t_error_log_tab全局结构体 ERROR_LOG_TABLE_T(data/fault_warn_log/fault_warn_log.h:692、703)故障日志表;本文件读 u_bms_display_error.bit.u8_bms_lost、u_inv_display_error.bit.u8_inv_lost/u8_grid_loss_fault、u_accessories_display_error.bit.u8_grid_meter_lost/u8_pv_meter_lost
INV_DISPLAY_ERROR_U联合体(data/fault_warn_log/fault_warn_log.h:537-583)逆变器显示故障位域,u8_grid_loss_fault 位于 BYTE3 bit0(fault_warn_log.h:574)
BMS_DISPLAY_ERROR_U联合体(fault_warn_log.h:488-535)BMS 显示故障位域,u8_bms_lost 位于 BYTE0 bit0(fault_warn_log.h:495)
ACCESSORIES_DISPLAY_ERROR_U联合体(fault_warn_log.h:585-632)附件(电表/充电桩等)显示故障位域,u8_grid_meter_lost/u8_pv_meter_lost 位于 BYTE0 bit0/bit1(fault_warn_log.h:592-593)
sys_current_status_color全局变量(STATUS_LED_COLOR_E,定义于 hmi/led/app_led.c:44)长灯带(WS2812)系统状态颜色,本文件在 hmi/led.c:654 写入
g_t_logic_info.t_config_data.u8_system_mode全局结构体字段(logic/logic.h:317)系统类型(DC/AC/Hybird),电表灯判定用
g_t_app_info.u8_app_connect_flag全局结构体字段(net/ems.h:353)APP 直连标志,联网灯最高优先级
g_stEMSInfo.bIsBuiltSocket / .bIsLogin全局结构体字段(net/ems.h:285-286、467)云端 socket 建立/登录标志
g_t_wireless_info.u8linkstatus / .u8_wireless_found全局结构体字段(midware/ethernt/wireless/wireless_driver.h:88)路由/无线模块连接与发现标志

3. 函数清单

函数名作用域(static/全局)说明(一句话)
led_display_test全局(hmi/led.c:42)开机/切换机型时的灯显自检:按 type 依次点亮全部可用 LED(每套流程末尾 OSTimeDlyHMSM(...,300)),用于产线与上电确认硬件
analysis_error_codestatic(hmi/led.c:125)取 32 位故障码中最低的置位 bit 序号,作为 5 位灯显编码(≥31 时归 0)
led_display全局(hmi/led.c:157)指示灯周期刷新主体:计算 6 个逻辑灯状态,再按 type 分支驱动对应灯板

本文件共 3 个函数,已全部列出。

4. 核心逻辑解析

4.1 整体结构

led_display(type)(hmi/led.c:157-1083)是一次调用完成全部工作的无状态机式条件刷新函数,可分三段:

  1. 升级闪烁计数(hmi/led.c:179-206)
  2. 6 个逻辑灯状态的统一计算(hmi/led.c:208-383)
  3. 按 type 分派到 5 种灯板的输出映射(hmi/led.c:386-1082)

所有中间状态都用函数内 static 变量保存(s_u8_normal_led_sts 等),因此 led_display() 必须被周期调用才能产生闪烁效果。

4.2 升级/下载指示状态机

if ((IsSystemDownload() == TRUE) || (IsSystemUpgrade() == TRUE))
    if (abs(s_u32_upgrade_tick - OSTimeGet()) > 200)
        { s_u32_upgrade_tick = OSTimeGet(); s_u8_upgrade_cnt++; }   // hmi/led.c:180-187

4.3 6 个逻辑灯状态的判定条件

逻辑灯变量判定逻辑(hmi/led.c 行号)
正常(绿)s_u8_normal_led_stscUPS → TRUE;任一故障码(ems_read_fault_code() / inverter_read_fault_code() / ..._extend() / ..._extend2() / bms_read_fault_code())→ FALSE;cNormalMode → TRUE;cCheckMode(开机自检)→ 每 500 ms 翻转一次;其他 → FALSE(208-238)
故障(红)s_u8_fault_led_sts + s_u8_error_led_stscUPS → FALSE;任一故障码(额外含 get_accessories_display_error_code())→ TRUE,并在故障期间每 100 ms 翻转 s_u8_error_led_sts 产生闪红;无故障 → FALSE(240-257)
电池(黄/电池灯)s_u8_battery_led_stsbms_get_ready_enable() → FALSE(电池未就绪);bms_get_connect_state() 且 bms_read_work_status() != FALSE → TRUE;已连接但未工作 → 每 500 ms 翻转;未连接 → FALSE(259-282)
电表s_u8_meter_led_sts分支一:亚克力灯板 + cUPS → 每 100 ms 翻转;分支二:AC_SYSTEM_MODE/HYBIRD_SYSTEM_MODE → 两表都连 TRUE,仅 PV 连每 200 ms 翻转,仅 GRID 连每 500 ms 翻转,都不连 FALSE;分支三:其他系统模式只判 GRID_METER 是否连接(284-333)
联网s_u8_net_led_sts、s_u8_net_led_color五级优先级(335-383),见 4.4
故障码灯l_u8_display_code仅亚克力灯板分支内计算,见 4.7

4.4 联网灯优先级与颜色

hmi/led.c:335-383 是按优先级排列的 if / else if 链:

优先级条件亮灭颜色 s_u8_net_led_color
1g_t_app_info.u8_app_connect_flag == TRUE(APP 直连)每 100 ms 翻转在 0 ↔ 2 之间交替(调色闪烁)
2g_stEMSInfo.bIsBuiltSocket && g_stEMSInfo.bIsLogin(已登录云端)常亮固定 2(绿)
3g_stEMSInfo.bIsBuiltSocket(已建 TCP,未登录)每 2000 ms 翻转在 0 ↔ 2 之间交替
4g_t_wireless_info.u8linkstatus(路由已连)每 1000 ms 翻转固定 1(红)
5g_t_wireless_info.u8_wireless_found(已发现无线模块)每 500 ms 翻转在 0 ↔ 1 之间交替
—以上都不满足灭0

颜色值语义:0 = 灭,1 = 红,2 = 绿(见 hmi/led.c:170 注释、4.8 双色板用法)。

4.5 闪烁节拍实现方式

所有闪烁统一使用"绝对时间差 > 阈值则翻转"的写法,例如:

if (abs(s_u32_net_tick - OSTimeGet()) > 2000)
{ s_u32_net_tick = OSTimeGet(); s_u8_net_led_sts = (s_u8_net_led_sts == FALSE); }

周期为 2×阈值(翻转间隔 + 保持时间),即 100 ms 阈值 → 200 ms 完整周期;2000 ms 阈值 → 4 s 完整周期。基准时钟为 uCOS-II 的 OSTimeGet()(1 tick = 1 ms,UCOSII/uCOS-CONFIG/os_cfg.h:51 OS_TICKS_PER_SEC = 1000u)。

4.6 各种灯板的输出映射

(1) DISPLAY_LCD_CHARACTER_E(字符 LCD 面板,hmi/led.c:386-433)

4 颗独立 LED 直接映射:s_u8_normal_led_sts → LED_Green_ON/OFF;s_u8_fault_led_sts → LED_Red;s_u8_battery_led_sts → LED_Yellow;s_u8_net_led_sts → LED_Blue。特例:透传模式且未识别到逆变器(get_passthrough_flag() && get_inverter_type() == INVERTER_NULL)时 4 颗全亮。

(2) DISPLAY_LED_LAMP_STRIP_E(四代机灯条,hmi/led.c:434-530)

升级时用 s_u8_upgrade_cnt 生成 4 拍流水覆盖状态灯:下载态 l_u8_led_sts = 3-(cnt%4),升级态 l_u8_led_sts = cnt%4;4 拍分别把"故障 / 正常+电池 / 电表 / 全灭"打到 s_u8_normal_led_sts/s_u8_fault_led_sts/s_u8_battery_led_sts/s_u8_meter_led_sts。输出映射:led_db0=正常、led_db1=故障、led_db2=电池、led_db3=电表、led_db4=联网。

(3) DISPLAY_LED_BICOLOR_E(双色小灯板,hmi/led.c:531-620)

升级时用 3 拍流水(下载 cnt%3,升级 2-(cnt%3)),并在升级时强制 s_u8_fault_led_color = 2。正常输出:led_db0=正常、led_db1=常灭、led_db2/db3=故障双色(s_u8_fault_led_color==2 时点 db2,否则点 db3)、led_db4/db5=联网双色(s_u8_net_led_color==1 点 db5 红,==2 点 db4 绿)。

(4) DISPLAY_LCD_RKP_E(林内项目长灯带,hmi/led.c:621-658)

不驱动任何 GPIO,只做一次 4 值状态归约 + 去抖:

has_fault   = ems/inv/inv_ext/inv_ext2/bms 故障码 || get_accessories_display_error_code();
has_warning = !has_fault && bms_get_connect_state() && !bms_read_work_status();
has_normal  = !has_fault && !has_warning && (run_mode == cNormalMode || run_mode == cUPS);
if (has_fault) new_status = SYS_STATUS_FAULT_LED_RED;          // 2 红
else if (has_warning) new_status = SYS_STATUS_WARNING_LED_YELLOW; // 3 黄
else if (has_normal) new_status = SYS_STATUS_NORMAL_LED_GREEN;    // 1 绿
else new_status = SYS_STATUS_NOT_RUN_LED_OFF;                     // 0 灭

去抖:状态变化时只刷新 s_u32_last_change,连续保持 200 ms 不变才把 new_status 写入 sys_current_status_color(hmi/led.c:650-656)。s_u8_last_status 初值 0xFF 作为"尚未确定"哨兵,保证首次必写。该全局量被 hmi/led/app_led.c:89-93 读取。

(5) DISPLAY_LED_LAMP_PANEL_E(五代机亚克力灯板,hmi/led.c:659-1081)

引脚分配:LED_Red = 系统红;led_db0 = 联网;led_db1 = 电池;led_db2 = 系统绿/故障码 bit0(二选一);led_db3 = 电表/故障码;led_db4..db7 = SOC 柱或故障码 bit1..bit4;LED_Blue = SOC 满或故障码 bit0。

4.7 故障码 5 位灯显编码

analysis_error_code()(hmi/led.c:125-148)从 bit0 开始扫描 32 位故障码,返回最低置位 bit 的序号;若扫描完未找到(值为 0)或结果 ≥31,则返回 0。返回值 l_u8_display_code 的 bit0..bit4 分别驱动 LED_Blue、led_db4、led_db5、led_db6、led_db7(hmi/led.c:939-982)。

亚克力灯板的故障分支按优先级四级互斥(hmi/led.c:779-937):

优先级条件行为
1通讯故障:u_bms_display_error.bit.u8_bms_lost \\u_inv_display_error.bit.u8_inv_lost \\u_accessories_display_error.bit.u8_grid_meter_lost \\...u8_pv_meter_lostled_db2 灭,LED_Red 亮(逆变器掉线时用 s_u8_error_led_sts 闪红,其余常亮),l_u8_display_code = 0
2get_bms_display_error_code() 非 0系统红常亮,电池灯用 s_u8_error_led_sts 闪烁,显示码 = BMS 故障码最低位
3get_inv_display_error_code() 非 0系统红闪烁(由 s_u8_error_led_sts),电池灯正常,显示码 = 逆变器故障码最低位
4get_accessories_display_error_code() 非 0系统红常亮,电表灯用 s_u8_error_led_sts 闪烁,显示码 = 附件故障码最低位
—均无(但 s_u8_fault_led_sts 为真)仅按 s_u8_error_led_sts 闪红,显示码 0

正常的"无故障"分支(hmi/led.c:984-1070):u_inv_display_error.bit.u8_grid_loss_fault(市电丢失)→ LED_Red 常亮、led_db2 灭;否则 LED_Red 灭、led_db2 跟随 s_u8_normal_led_sts。SOC 柱按 bms_read_total_soc() 分 6 档点亮 led_db4..db7 + LED_Blue:

bms_read_total_soc() 区间(单位 0.1%)点亮
≤ 50(≤5%)全灭
≤ 200(≤20%)db7
≤ 400(≤40%)db6、db7
≤ 600(≤60%)db5、db6、db7
≤ 800(≤80%)db4~db7
> 800(>80%)LED_Blue + db4~db7

最后无论何种分支,都用 s_u8_net_led_sts 驱动 led_db0(hmi/led.c:1073-1080)。

4.8 led_display_test() 开机自检

hmi/led.c:42-116 按 type 依次动作,每套流程结束时 OSTimeDlyHMSM(0,0,0,300) 挂起 300 ms:

该函数由 hmi/key.c:8896 在 task_hmi_parse() 初始化阶段调用一次,会阻塞 HMI 任务约 300~600 ms。

5. 对外接口

本文件导出

名称类型使用方
led_display_test全局函数(声明于 hmi/led.h:22)hmi/key.c:8896
led_display全局函数(声明于 hmi/led.h:23)hmi/key.c:8953

本文件不导出任何全局变量(自身定义的都是函数内 static)。

本文件调用的外部函数/变量

名称来源模块
LED_Green_ON/OFF、LED_Red_ON/OFF、LED_Yellow_ON/OFF、LED_Blue_ON/OFF、led_db0_on/off…led_db7_on/offhardware/gpio/gpio.c(声明 hardware/gpio/gpio.h:137-148)
OSTimeGet、OSTimeDlyHMSMuCOS-II
absC 标准库
IsSystemDownload、IsSystemUpgradenet/ems_download.c(声明 net/ems_download.h:41-42)
ems_read_fault_codedata/data.c(声明 data/data.h:127)
inverter_read_run_mode、inverter_read_fault_code、inverter_read_fault_code_extend、inverter_read_fault_code_extend2、get_inverter_typemidware/inverter/inverter.c(声明 inverter.h:2011-2019、1940)
bms_get_ready_enable、bms_get_connect_state、bms_read_work_status、bms_read_fault_code、bms_read_total_socmidware/bms/bms.c
meter_read_connect_statusmidware/meter/meter.c
get_bms_display_error_code、get_inv_display_error_code、get_accessories_display_error_codedata/fault_warn_log/fault_warn_log.c
get_passthrough_flagmidware/debug/ate.c
g_t_error_log_tabdata/fault_warn_log/fault_warn_log.c(SDRAM 固定地址)
g_t_logic_infologic/logic.c
g_t_app_infonet/ems.c
g_stEMSInfomidware/ethernt/ethernet.c
g_t_wireless_infomidware/ethernt/wireless/
sys_current_status_color写出(hmi/led.c:654),定义于 hmi/led/app_led.c:44

6. 依赖关系

依赖(本文件 include):led.h(13)、fault_warn_log.h(14)、key.h(15)、gpio.h(16)、ems.h(17)、meter.h(18)、logic.h(19)、inverter.h(20)、alphaess_comm_usart.h(21)、ethernet.h(22)、data.h(23)、bms.h(24)、ems_download.h(25)、ate.h(26)。

被依赖:

7. 备注与风险点