UI 待机显示页接入 UA/UB/UC/IA/IB/IC 六路实时值(v1.1)

- ui_standby.c:v1 占位(6 行恒 0.00A)→ ui_data 通道一按 seq 门控取帧,
  yc 语义下标 {0,1,2,4,5,6}(跳 UN/IN);无首帧/坏质显 --;定点格式化复用
  ui_w_editor_fmt_scaled;单位随 eng(引脚档不挂),口径逐字对齐 ui_page_ac.c
- ui_standby.h:头注与修改记录同步
- 文档 §5.2 按新口径改写;§1 R2 改为新需求口径(不再引 mockup);§9 对应
  开放问题销项删行;版本 v1.4

验证:模拟器 0 错 0 警 + 菜单行/内容页/编码规范门禁 PASS + Keil 0 错 0 警;
--standby 截图双分支实证(UA/IA 显值、UB/UC/IB/IC 显 --)。
This commit is contained in:
2026-11-13 13:11:42 +08:00
parent 40a2816a99
commit 5bab248dee
7 changed files with 157 additions and 42 deletions
+119 -12
View File
@@ -1,6 +1,7 @@
/*
* 模块名称:UI Standby (待机显示页)
* 模块功能:长时间无按键操作时自动切入的默认界面(6 路电流值 + 分隔线 + 底部时钟);
* 模块功能:长时间无按键操作时自动切入的默认界面(UA/UB/UC/IA/IB/IC 六路实时值 + 分隔线 + 底部时钟);
* 数值经 ui_data 通道一实时帧 yc[](App 层装配,本文件零 App include),口径同 ui_page_ac.c;
* 屏幕覆盖层模式——进入保存前屏与焦点、ENTER(确认键)还原,其余键忽略;
* 空闲检测 = lv_timer(1s 周期),活动通知由菜单/内容页键事件挂钩
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
@@ -8,6 +9,9 @@
* 创建日期:2026-09-14
* 修改记录:
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/子系统设计/运行与自检记录设计说明.md §5.2)
* v1.1 2026-11-13 DTU 项目组 v1 占位(6 行电流恒 0.00A)→ UA/UB/UC/IA/IB/IC 实时值:
* ui_data 通道一按 seq 门控取帧;无首帧/坏质显 "--";定点
* 格式化复用 ui_w_editor_fmt_scaled;单位随 eng(引脚档不挂)
*/
/* 头文件包含区 */
@@ -16,9 +20,11 @@
#include "ui_standby.h"
#include "lvgl.h"
#include "ui_data.h"
#include "ui_menu_view.h"
#include "ui_style.h"
#include "ui_tokens.h"
#include "ui_w_editor.h"
#define DBG_TAG "[UI_STANDBY]"
#include "dbg_log.h"
@@ -27,24 +33,40 @@
/*
* 布局常量(设备像素;参考 mockups/待机显示页面.jpg):
* 屏幕宽高取令牌 UI_SCREEN_W/H;6 路电流值行自 y=28 起、行距 18
* 屏幕宽高取令牌 UI_SCREEN_W/H;六路实时值行自 y=28 起、行距 18
* (末行 y=118..130);分隔线 y=132;底部时钟 y=140 居中
*/
#define SB_CH_COUNT 6u /* 电流通道数 */
#define SB_CH_COUNT 6u /* 显示通道数(六路主要电力量;yc 下标见 s_ch_yc) */
#define SB_ROW_Y0 28 /* 首数据行顶 y */
#define SB_PITCH 18 /* 行距(相邻行槽顶间距) */
#define SB_LABEL_X 24 /* 通道名 x(Ib/Ic/...) */
#define SB_LABEL_X 24 /* 通道名 x(UA/UB/UC/IA/IB/IC) */
#define SB_EQ_X 72 /* "=" 号 x */
#define SB_VALUE_X 96 /* 数值 x(0.00A;v1 占位,待交流量标定管线接入实时值) */
#define SB_VALUE_X 96 /* 数值 x(数字+单位 或 "--") */
/* 值串缓冲长度:最坏 "2147483.647V" = 12 + NUL,取 16 留余量 */
#define SB_VAL_BUF_LEN 16u
#define SB_INVALID "--" /* 空值串(同交流量页 AC_INVALID) */
#define SB_DECIMALS 3u /* 电压/电流小数位(同交流量页 AC_IA_DECIMALS) */
/* 不可信品质合集:无效 / 未攒满一周波 / 透传码值 / 自检异常 / 闭锁 / 越程
* (逐字同 ui_page_ac.c 的 AC_Q_BAD——两处判据不可能漂移) */
#define SB_Q_BAD (UI_DATA_Q_IV | UI_DATA_Q_NT | UI_DATA_Q_RAW | UI_DATA_Q_SB | \
UI_DATA_Q_BL | UI_DATA_Q_OV)
#define SB_LINE_Y 132 /* 分隔线 y(高 1px) */
#define SB_TIME_Y 140 /* 底部时钟放置 y(居中) */
/* 静态变量定义区 */
/* 通道名与占位数值(Flash;全 ASCII,无需中文字形) */
static const char *const s_ch_name[SB_CH_COUNT] = { "Ib", "Ic", "Io", "Ia2", "Ib2", "Ic2" };
static const char *const s_ch_value[SB_CH_COUNT] = { "0.00A", "0.00A", "0.00A", "0.00A", "0.00A", "0.00A" };
/* 通道名表 + yc[] 语义下标映射(Flash;全 ASCII,无需中文字形)。
* 下标 = adc_semantic_t 序(UA/UB/UC/UN/IA/IB/IC/IN/TEMP):跳过 UN(3)/IN(7)——
* 用户点名显示六路(2026-11-13),且 UN 本台架永久无数据,摆一排恒 "--" 的假通道
* 不如不摆(取舍逻辑同交流量页只显 Ua/U0/Ia,docs/UI设计/页面扩充详细方案.md §3.1.1) */
static const char *const s_ch_name[SB_CH_COUNT] = { "UA", "UB", "UC", "IA", "IB", "IC" };
static const uint8_t s_ch_yc[SB_CH_COUNT] = { 0u, 1u, 2u, 4u, 5u, 6u };
/* 帧缓存:发布序号变化才整帧拷一次(页面侧约定 = ui_data.h 头注 / UI_数据供给设计说明.md §5.4) */
static ui_data_rt_t s_rt;
static uint32_t s_seq;
static lv_obj_t *s_scr; /* 待机屏(init 时建、常驻不销毁) */
static lv_obj_t *s_cont; /* 全屏容器(焦点/键入口 + 自绘载体,无子对象) */
@@ -75,6 +97,85 @@ static bool sb_areas_intersect(const lv_area_t *a, const lv_area_t *b) {
return (x1 <= x2 && y1 <= y2);
}
/*
* 函数功能:把常量值串安全搬进显示缓冲(替代 strcpy,规范 7.5;同 ui_page_ac.c 的 ac_put)
* 入口参数:a_dst - 目标缓冲(SB_VAL_BUF_LEN) char *
* a_lit - 源字面量(编译期串,长度由宏用 sizeof 算好) const char *
* a_len - 需拷贝字节数(不含 NUL) uint32_t
* 返回值:无
* 限定条件:a_dst/a_lit 非 NULL;a_len 超缓冲时截断而不是越界
*/
static void sb_put(char *a_dst, const char *a_lit, uint32_t a_len) {
if (a_len > (SB_VAL_BUF_LEN - 1u)) {
a_len = SB_VAL_BUF_LEN - 1u;
}
(void)memcpy(a_dst, a_lit, a_len);
a_dst[a_len] = (char)0;
}
/* 值串落屏统一走这里:长度由 sizeof 在调用点算,改串不会漏改长度 */
#define SB_PUT(a_dst, a_lit) sb_put((a_dst), (a_lit), (uint32_t)(sizeof(a_lit) - 1u))
/*
* 函数功能:取用最新实时帧(只在发布序号变化时整帧拷)——读法同 ui_page_ac.c 的 ac_frame_ready
* 入口参数:无
* 返回值:1 - 有可用帧;0 - 首帧未到或本帧无效 uint8_t
* 限定条件:UI 任务绘制上下文
* 函数说明:读失败(首帧未到)时清缓存并记住本次序号,避免每次重绘重复尝试;下一帧序号
* 必然变化 → 自动恢复。待机 1s 定时器整屏 invalidate 就是数值刷新节拍,不新增定时器
*/
static uint8_t sb_frame_ready(void) {
uint32_t now = ui_data_rt_seq();
if (now != s_seq) {
s_seq = now;
if (ui_data_rt(&s_rt) != 0) {
(void)memset(&s_rt, 0, sizeof(s_rt));
return 0u;
}
}
return (s_rt.valid != 0u) ? 1u : 0u;
}
/*
* 函数功能:拼一行值串(数字 + 单位,或 "--")
* 入口参数:a_idx - 显示行下标 0..5 uint32_t
* a_buf - 输出缓冲 char *
* a_len - 缓冲容量(含 NUL) uint32_t
* 返回值:无
* 限定条件:UI 任务绘制上下文
* 函数说明:口径同 ui_page_ac.c——无首帧或品质带 SB_Q_BAD 一律 "--"("有数但不可信"与
* "没有数"同形);数字走共享定点格式化 ui_w_editor_fmt_scaled(3 位小数 =
* 10^3 定点,负值钳 0 交给品质位解释),页面侧不引 %f 软浮点打印。单位随 eng:
* 二次/一次值档 UA/UB/UC 挂 "V"、IA/IB/IC 挂 "A";ENG_PIN 档不挂单位——引脚档
* 数字是 ADC 引脚电压而非端子电流量,挂单位就是替用户完成没做的换算(交流量页
* 同档另设量纲口径行标注,待机屏无第 7 行可标,故数字照显、单位缺席)
*/
static void sb_value_str(uint32_t a_idx, char *a_buf, uint32_t a_len) {
const ui_data_yc_t *p;
uint32_t n;
if ((a_idx >= SB_CH_COUNT) || (sb_frame_ready() == 0u) ||
(s_ch_yc[a_idx] >= (uint8_t)UI_DATA_YC_N)) {
SB_PUT(a_buf, SB_INVALID);
return;
}
p = &s_rt.yc[s_ch_yc[a_idx]];
if ((p->qds & (uint8_t)SB_Q_BAD) != 0u) {
SB_PUT(a_buf, SB_INVALID);
return;
}
ui_w_editor_fmt_scaled((p->val > 0.0f) ? (int32_t)((p->val * 1000.0f) + 0.5f) : 0,
SB_DECIMALS, a_buf, a_len);
if (s_rt.eng != (uint8_t)UI_DATA_ENG_PIN) {
n = (uint32_t)strlen(a_buf);
if ((n + 1u) < a_len) {
a_buf[n] = (a_idx < 3u) ? 'V' : 'A';
a_buf[n + 1u] = (char)0;
}
}
}
/*
* 函数功能:绘制居中单行文本(底部时钟)
* 入口参数:layer - 绘制层 lv_layer_t *
@@ -100,11 +201,12 @@ static void sb_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y
}
/*
* 函数功能:待机屏自绘(6 路电流值 + 分隔线 + 底部时钟;逐行 culling)
* 函数功能:待机屏自绘(六路实时值 + 分隔线 + 底部时钟;逐行 culling)
* 入口参数:e - 事件指针 lv_event_t *
* 返回值:无
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,待机模块已初始化
* 函数说明:1bpp 极性 white=暗墨——文本/分隔线均白色;数值 v1 占位 0.00A
* 函数说明:1bpp 极性 white=暗墨——文本/分隔线均白色;数值逐行现拼(sb_value_str),
* 待机 1s invalidate 即数值刷新节拍
*/
static void sb_draw_cb(lv_event_t *e) {
lv_layer_t *layer = lv_event_get_layer(e);
@@ -113,6 +215,7 @@ static void sb_draw_cb(lv_event_t *e) {
int32_t row_y = SB_ROW_Y0 + (int32_t)i * SB_PITCH;
lv_area_t strip;
lv_draw_label_dsc_t ld;
char vb[SB_VAL_BUF_LEN];
strip.x1 = 0;
strip.x2 = UI_SCREEN_W - 1;
@@ -142,8 +245,8 @@ static void sb_draw_cb(lv_event_t *e) {
lv_draw_label_dsc_init(&ld);
ld.base.layer = layer;
ld.text = s_ch_value[i];
ld.text_static = 1;
sb_value_str(i, vb, (uint32_t)sizeof(vb)); /* 栈缓冲同帧有效(同底部时钟 ts 模式) */
ld.text = vb;
ld.color = UI_COL_FG;
ld.ofs_x = SB_VALUE_X;
ld.ofs_y = 0;
@@ -197,6 +300,10 @@ static void sb_enter(void) {
if (s_active || s_scr == NULL) {
return;
}
/* 进入即复位帧缓存(同交流量页 ac_init 开页复位理由:不沿用上次的陈旧帧号,
* 强制下一次绘制重取最新帧) */
s_seq = 0u;
(void)memset(&s_rt, 0, sizeof(s_rt));
s_prev_scr = lv_screen_active();
g = lv_group_get_default();
s_prev_focus = (g != NULL) ? lv_group_get_focused(g) : NULL;
+3 -1
View File
@@ -1,6 +1,7 @@
/*
* 模块名称:UI Standby (待机显示页)
* 模块功能:长时间无按键操作时自动切入的默认界面(6 路电流值 + 分隔线 + 底部时钟);
* 模块功能:长时间无按键操作时自动切入的默认界面(UA/UB/UC/IA/IB/IC 六路实时值 + 分隔线 + 底部时钟);
* 数值经 ui_data 通道一实时帧 yc[](口径同 ui_page_ac.c);
* 屏幕覆盖层模式——进入保存前屏与焦点、ENTER(确认键)还原,其余键忽略;
* 空闲检测 = lv_timer(1s 周期),活动通知由菜单/内容页键事件挂钩
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
@@ -8,6 +9,7 @@
* 创建日期:2026-09-14
* 修改记录:
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/子系统设计/运行与自检记录设计说明.md §5.2)
* v1.1 2026-11-13 DTU 项目组 6 路电流占位 → UA/UB/UC/IA/IB/IC 实时值(口径同 ui_page_ac.c)
*/
#ifndef UI_STANDBY_H