4380098cc1
三页原先的读数是 Flash 里的参考项目字面量(交流量 24 行、直流量 3 行、装置信息 6 行,含 "软件校验 4454""程序日期 2024.08.27""第 10 页"这类与本机无关的假值)。本笔把它们接到 task-14 落地的快照通道:页面只读快照、零 App include(分层方向基线仍 3 条,不增不减)。 装置信息(6 行 → 8 行) - 型号/软件版本/硬件版本/软件校验/程序日期/运行时长取 info 帧;MAC/IP 取 net_cfg RAM 副本 (同层 BSP→BSP,与网口设置页同一个 net_cfg_fmt_ipv4,不另起第二套格式化口径) - 行几何重排:标签去全角冒号、值列左对齐 x=56——原 x=86 是参考图"短值"的产物,容不下 17 字符 MAC(102 px);8 行按 13 px 行距排到 129,不与页脚(143)相撞 - 页脚从固定"第 10 页"改真页码"第 1 页,共 1 页"(屏上不该出现与本机无关的数字, Lead 裁定 2026-10-25);副标题属产品口径,本批不动 - 快照定长字符域按**容量扫**而非 strlen:契约写明这些域不保证 NUL 终止,strlen 就是越界 读——模拟器里后面紧跟别的常量大概率侥幸,板端 Flash 布局一变才翻车且不报错 交流量(24 行 → 7 行) - Ua/U0/Ia 走基波相量实例,Ia2/Ia5 走谐波实例(快照 ph[] 按写侧 k_inst[] 序发布),Hz 走 测频新鲜度,第 7 行是量纲口径说明行(eng → 未标定/二次值/一次值,标定闭环自动改口) - 不做 24 行:V0.1 只有 8 路电气量、5 路削顶无采样源、相量实例 5 个,照抄就是 17 行 "--" 的假骨架(docs/UI设计/页面扩充详细方案.md §3.1.1 同一取舍,已补落地注) - 品质位判空:IV/NT/RAW/自检异常/闭锁/越程一律 "--"——削顶通道快照里还留着上一帧的数, 照抄等于把坏数当实测送进人眼;"没有数"与"有数但不可信"在屏上必须同形 - 格式化复用 ui_w_editor_fmt_scaled(定点整数,与整定页同一真源),页面不写 %f:MicroLIB 软浮点打印一进镜像就是几百字节 Flash,而模拟器(宿主 CRT)永远照不出这笔代价 直流量(3 行 → 2 行) - V0.1 板上没有直流采样通道(ADC_SEM 只有 8 路电气 + 温度,104 点表 0x401E/0x401F 亦注 "FTU 无")→ 温度行取码值并加"码"前缀(把"这不是温度"写进屏上而非注释里),通道行 如实"未配置";菜单语义与点表一致(§3.1.2 方案①) 三条被现场验证的纪律与一处门禁有效性证据 - 帧缓存按发布序号门控(实时帧 ~200 B 只在序号变化时整帧拷一次),开页 init_cb 复位缓存 ——否则重开页面会沿用上次开页的帧号,首帧前的 "--" 状态可能被永久留在屏上 - 值串落屏统一走 *_PUT 宏(长度取调用点 sizeof):代码规范 7.5 禁 strcpy,写串与算长同处 - 运行时长过一天的"天"字被 font-charset 门禁拦下(不在 183 字子集,上屏即空白方块): 为一个运行时才出现的格式字符扩字库要付 27 B RO + 一次字体重生成,改用 ASCII"d"——顺带 成为该门禁有效性的现场证据(这类缺陷平时既无日志也无报错) - 三页每次编辑后重核 BOM:丢 BOM 时 ARMCC 按 CP936 解码,报的是 #18/#274 这类**假语法错** (本笔实测复现一次,修复只补 3 字节 EF BB BF),模拟器(MSVC)完全照不出来 验证 - @build:0 错误 0 警告;模拟器:0 警告 - 内容页回归 14 项 PASS(文本断言逐行核对三页新值:未标定口径、Hz "--"、码2048、真页码; 其余 8 页逐字节不变);菜单 8 状态 PASS(池 5368 B);开页-关页往返池 5448 B 不变 - 三页刷新黄金参考前均出图肉眼确认:行不重叠、值列不越屏、口径行可见 - 全量钩子(--all-files,本笔 + 下一笔基线合并后的树):41 项 Passed;唯一红项是 mem-numbers / mem-budget —— 只因 Flash/RAM 台账未回填(docs/内存管理/** 与 scripts/ram_baseline.tsv 是单写者禁区,归 Lead),故本笔 --no-verify 体积(相对 HEAD 台账 Code 217204 / RO 21504 / RW 1256 / ZI 132680) - Code +1440、RO −512(删三页 Flash 行表与参考遗留串)、RW +12、ZI +484(三页帧缓存 200 B + 92 B + 序号等)→ Flash 合计 +940 B、RAM +496 B - .map 明细:ac_refresh 202 B、dc_refresh 164 B、di_refresh 290 B、di_fmt_uptime 92 B 待台架实测:真机读数与 104 上位机对照、标定完成后第 7 行自动变"二次值"、MAC/IP 与网口 设置页一致、页面只在重绘时取新帧的实际刷新节拍。 gate: only mem-budget/mem-numbers pending lead ledger backfill 像素基线按 Lead 口径单独提交(下一笔 test(ui-golden)):本笔单独 checkout 时 ui-golden 会 报三页差异,属预期拆分,不是回归——上面的钩子结论是在"本笔 + 下一笔"的合并树上跑出来的。 自查:三页 BOM = EF BB BF、CR = 0、U+FFFD = 0、字面量纯 ASCII(中文只在带 BOM 文件里)。
153 lines
6.0 KiB
C
153 lines
6.0 KiB
C
/*
|
||
* 模块名称:UI Page DC (直流量内容页)
|
||
* 模块功能:直流量叶子节点(node 4)内容页——2 行动态列表:温度(STM32 片内 ADC 透传码值,
|
||
* 未标定)+ 直流通道(V0.1 板上无直流采样通道,值列如实显示"未配置");数据取自
|
||
* ui_data 实时帧(App 层装配,本文件零 App include);向框架 ui_content_page 提供
|
||
* 页面描述符(零 LVGL 对象)
|
||
* 为什么只有 2 行:参考图 21 的"3 行直流读数"在本板无采样源(ADC_SEM 只有 8 路电气 + 温度,
|
||
* 104 点表 0x401E/0x401F 亦注明"FTU 无")——照抄就是三行假数(取舍见
|
||
* docs/UI设计/页面扩充详细方案.md §3.1.2 方案①,菜单语义与点表保持一致)
|
||
* 空值口径:温度通道无效时显 "--";码值一律不挂单位(挂上"℃"就是替用户完成了没做的标定)
|
||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-09-09
|
||
* 修改记录:
|
||
* 2026-09-09 王建锋 创建:自 ui_content_page 单体拆出(数据原样迁移,零改动)
|
||
* v2.0 2026-10-25 王建锋 道E task-15 回炉:3 行 Flash 假数(ZL01/ZL02/Pa1)→ 2 行快照
|
||
* 真值;温度取 yc[ADC_SEM_TEMP] 并显式标注是码值
|
||
*/
|
||
|
||
/* 头文件包含区 */
|
||
#include <string.h>
|
||
|
||
#include "ui_page_dc.h"
|
||
|
||
#include "ui_data.h"
|
||
#include "ui_tokens.h"
|
||
#include "ui_w_editor.h"
|
||
|
||
/* 私有宏定义区 */
|
||
|
||
/* 温度通道在快照 yc[] 里的语义下标 = adc_semantic_t 的 TEMP(最后一项,随通道表漂移;
|
||
* 由 test/host/ui_data 的"下标空间与 App/algo/adc_input.h 逐行一致"断言兜住) */
|
||
#define DC_YC_TEMP 8u
|
||
#define DC_ROW_N 2u
|
||
#define DC_INVALID "--"
|
||
/* 温度值列前缀:一个"码"字把"这是 12 位原始码、不是温度"写进屏上而不是注释里 */
|
||
#define DC_CODE_PREFIX "码"
|
||
|
||
/* 静态变量定义区 */
|
||
|
||
/* 帧缓存(按发布序号门控,同交流量页) */
|
||
static ui_data_rt_t s_rt;
|
||
static uint32_t s_seq;
|
||
|
||
/* 函数定义区 */
|
||
|
||
/*
|
||
* 函数功能:把常量串安全搬进显示缓冲(替代 strcpy,规范 7.5)
|
||
* 入口参数:a_dst - 目标缓冲(框架 UI_BUF_STRLEN) char *
|
||
* a_lit - 源字面量(长度由宏用 sizeof 算好) const char *
|
||
* a_len - 需拷贝字节数(不含 NUL) uint32_t
|
||
* 返回值:无
|
||
* 限定条件:a_dst/a_lit 非 NULL;a_len 超缓冲按缓冲截断
|
||
* 函数说明:代码规范 7.5 禁 strcpy;长度来自调用点 sizeof,写串与算长同一处
|
||
*/
|
||
static void dc_put(char *a_dst, const char *a_lit, uint32_t a_len) {
|
||
if (a_len > ((uint32_t)UI_BUF_STRLEN - 1u)) {
|
||
a_len = (uint32_t)UI_BUF_STRLEN - 1u;
|
||
}
|
||
(void)memcpy(a_dst, a_lit, a_len);
|
||
a_dst[a_len] = (char)0;
|
||
}
|
||
|
||
#define DC_PUT(a_dst, a_lit) dc_put((a_dst), (a_lit), (uint32_t)(sizeof(a_lit) - 1u))
|
||
|
||
/*
|
||
* 函数功能:取用最新实时帧(只在发布序号变化时整帧拷)
|
||
* 入口参数:无
|
||
* 返回值:1 - 有可用帧;0 - 首帧未到或本帧无效 uint8_t
|
||
* 限定条件:uiTask 绘制上下文
|
||
*/
|
||
static uint8_t dc_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;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:开页复位缓存(强制重取最新帧)
|
||
* 入口参数:无
|
||
* 返回值:无
|
||
*/
|
||
static void dc_init(void) {
|
||
s_seq = 0u;
|
||
(void)memset(&s_rt, 0, sizeof(s_rt));
|
||
}
|
||
|
||
/*
|
||
* 函数功能:逐行取数(第 1 行温度码值、第 2 行直流通道未配置)
|
||
* 入口参数:a_row - 全局行下标 0..1 uint16_t
|
||
* a_name - 名输出缓冲(框架 UI_BUF_STRLEN) char *
|
||
* a_value - 值输出缓冲 char *
|
||
* 返回值:无
|
||
* 限定条件:uiTask 绘制上下文
|
||
* 函数说明:温度行的值列形如"码2048"——"码"字是把"这是 12 位原始码、不是温度"写进
|
||
* 屏上而不是写进注释;快照该路带 UI_DATA_Q_RAW(写侧因该通道不参与线性标定而置位),
|
||
* 这里同时按品质位判无效,两处任一说话都足以显 "--"
|
||
*/
|
||
static void dc_refresh(uint16_t a_row, char *a_name, char *a_value) {
|
||
if (a_row == 0u) {
|
||
const ui_data_yc_t *p; /* 温度通道(只有本分支用得到,cppcheck 也这么判) */
|
||
|
||
DC_PUT(a_name, "温度");
|
||
if ((dc_frame_ready() == 0u) || (DC_YC_TEMP >= UI_DATA_YC_N)) {
|
||
DC_PUT(a_value, DC_INVALID);
|
||
return;
|
||
}
|
||
p = &s_rt.yc[DC_YC_TEMP];
|
||
if ((p->qds & (uint8_t)(UI_DATA_Q_IV | UI_DATA_Q_SB | UI_DATA_Q_BL)) != 0u) {
|
||
DC_PUT(a_value, DC_INVALID);
|
||
} else {
|
||
ui_w_editor_fmt_scaled((p->val > 0.0f) ? (int32_t)(p->val + 0.5f) : 0, 0u,
|
||
a_value, (uint32_t)UI_BUF_STRLEN);
|
||
/* 前缀"码":单位由品质位说话,不靠读的人猜(长度取 sizeof,改字不脱节) */
|
||
(void)memmove(a_value + (sizeof(DC_CODE_PREFIX) - 1u), a_value,
|
||
strlen(a_value) + 1u);
|
||
(void)memcpy(a_value, DC_CODE_PREFIX, sizeof(DC_CODE_PREFIX) - 1u);
|
||
}
|
||
return;
|
||
}
|
||
|
||
DC_PUT(a_name, "直流通道");
|
||
DC_PUT(a_value, "未配置");
|
||
}
|
||
|
||
/*
|
||
* 页面描述符(外部链接:生成物 ui_page_registry.c 按菜单树 #page=dc 绑定引用):
|
||
* 2 行单页列表页;band_h 必须 >0(选中行黑字需白带,同交流量页约定)
|
||
*/
|
||
const content_page_def_t ui_page_dc_desc = {
|
||
.id = "dc",
|
||
.title = "直流量",
|
||
.selectable = 1u,
|
||
.top_y = UI_LIST_TOP,
|
||
.pitch = UI_ROW_PITCH,
|
||
.band_h = UI_ROW_BAND_H,
|
||
.text_dy = 0,
|
||
.left_x = UI_LIST_LEFT_X,
|
||
.right_x = UI_LIST_RIGHT_X,
|
||
.rows_per_page = UI_LIST_ROWS,
|
||
.row_count = DC_ROW_N,
|
||
.rows = NULL,
|
||
.init_cb = dc_init,
|
||
.refresh = dc_refresh,
|
||
};
|