UI子系统
super_agent_bot edited this page 2026-11-02 07:55:38 +08:00

UI子系统

MCU 没有物理屏幕: LVGL 渲染到 160x160、1bpp 的离屏缓冲, 经 TCP 7003 推送到远端客户端; 远端按键再回注 UI。

细节见 docs/UI设计/UI_设计架构.md、菜单页面设计.md、内容页架构.md、UI_界面制作流程.md、UI_自动化测试流程.md、RemoDispBus协议与接收设计说明.md。

1. 渲染与显示

项 值
屏幕 160 x 160 px
色深 1bpp 单色(MSB 优先), 帧缓冲 3200 B
图形库 LVGL 9.x(MCU 与 PC 模拟器共用)
主题 dark mono(单色深色)
渲染 LVGL 离屏渲染到 g_ui_fbuf
推流 ui_net_sink, TCP 7003, RemoDispBus 协议
刷新 uiTask 10 ms 循环
内存池 LV_MEM_SIZE = 40 KB

两条实证坑:

  1. I1 draw buffer 需要 +8 B palette 头, 不要按 1bpp 裸尺寸分配。
  2. 白底白字会整屏纯白: 1bpp 下颜色映射只有黑白, 绘制前必须设置正确的前景/背景。

2. 菜单树

42 节点菜单树总览

图: 菜单树 - 9 个菜单节点 + 33 个叶子.

  • 规模: 9 个菜单节点(含根)+ 33 个叶子 = 42 节点; 最大深度 4 级。
  • 根页 7 个一级条目: 装置信息 / 实时数据 / 参数定值 / 三遥设置 / 装置维护 / 通讯参数 / 记录查询。

2.1 三层代码架构

菜单级联框的几何布局

图: 级联框 - 子框在父框右侧逐级展开.

层 模块 职责
数据层 ui_menu_tab(生成物) g_menu_tab[42] 扁平父子索引表, 约 0.7 KB Flash
逻辑层 ui_menu 唯一 17 B 导航状态; ENTER/→ 进入, ESC/← 返回
显示层 ui_menu_view 持全部 LVGL 对象; 级联子框、选中行反色、▶ 标记
  • 页面 = 对表的一次 parent == 节点 过滤, 现算不落地。
  • 显示模型: 横向级联子框; 子框左缘 = 父框右缘(共享 1px 边框列); 子框顶边对齐父框选中行, 溢出时整框上移。
  • 改菜单: 编辑根目录 ui_menu_tree.txt(缩进即层级)→ 运行 tools/menu_gen/gen_menu.py → 导航/渲染代码零改动。

3. 内容页与待机屏

  • 内容页是独立全屏屏, 由框架一次性自绘(零 LVGL 子对象), ESC 返回菜单屏。
  • 同一时刻至多一个内容页打开; 菜单导航状态不压层, 返回即原样还原。
  • 已有内容页: 装置信息、交流量(24 行 / 每页 8, 共 3 页)、直流量(3 行)、用户密钥。
  • 其余叶子多数暂无内容页, 进入空白终点框。
  • 待机屏: 空闲超时(默认 60 s)自动切入, 仅确认键回菜单; 数据源同实时量页。

4. 密码与权限

项 值
查看密码 000(只读权限)
修改密码 123(修改权限)
存储 ui_pwd_def.h 编译期写入, 不落 Flash
流程 受保护叶子(ui_menu_tree.txt 行尾 #P)先 arm → 开密码页 → 确认后回调 → 先关页再续做进入动作

密码是编译期常量, 不是可配置安全机制; 现场不要把它当作强访问控制。

5. 中文字体

  • ui_font_cn_12.c: 宋体 12px、1bpp 子集, 当前 122 个唯一字 / 217 个字形。
  • 生成流程:
    1. tools/font_gen/extract_cn.py 扫描 UI 源码 → ui_cn_chars.txt;
    2. tools/font_gen/make_font.py 生成字体 C 文件。
  • 任何 UI 文案新增汉字后必须重跑此流程, 否则新字显示为空白方块。
  • 详见 docs/UI设计/UI_中文字体生成与配置.md。

6. PC 模拟器

MCU 与 PC 共用同一份 UI 源码(Drivers/BSP/UI/), 平台差异在 *_mcu.c / *_sim.c 后端。

# 一键构建(自动探测 VS2019/2022/2026 生成器)
simulator\build_sim.bat
# 运行
simulator\build\Debug\lvgl_sim.exe

UI 回归门禁:

.venv\Scripts\python.exe simulator/tests/check_menu_rows.py
.venv\Scripts\python.exe simulator/tests/check_content_pages.py
  • 菜单像素回归 + 内容页黄金参考 + 池水位校验;
  • 黄金参考更新流程见 docs/UI设计/UI_自动化测试流程.md;
  • 模拟器 vs 真机差距清单必查: docs/测试说明/模拟器差距清单.md(改动涉及网络/日志/硬件层前)。

7. 远程显示协议(RemoDispBus)

RemoDispBus 帧格式

图: RemoDispBus - TAG/CMD/LEN/DATA/CRC.

项 内容
传输 TCP 7003, 单连接(backlog=1)
帧 [TAG(1)][CMD(1)][LEN_H(1)][LEN_LO(1)][DATA(n)][CRC(1)]
方向 0xAA = 客户端→服务端; 0xBB = 服务端→客户端
校验 数据段逐字节异或(低 8 位, 不含 TAG/CMD/LEN)
字节序 多字节字段大端
最短帧 5 字节(LEN=0)
CMD 名称 请求 应答
0 KEEPLIVE 无 无(回显)
1 INIT 无 [宽u16][高u16][帧字节数u32](8 B)
2 KEY [按键码u8] 无(确认)
3 LCDMEM [起始偏移u32] [偏移u32][1bpp 位图 3200B](3204 B)

按键码: UP=0x02 / DOWN=0x40 / LEFT=0x10 / RIGHT=0x08 / ENTER=0x20 / ESC=0x01。

位图: 1bpp, MSB 优先(bit7 = 该字节第一个像素); 像素 (x,y) → byte=(y*W+x)/8、bit=7-(x%8); 位值 1=白、0=黑。

8. UI 改动流程

  1. 参考图 / 设计规格(P0);
  2. 在 ui_menu_tree.txt 或页面插件中实现(P1~P3);
  3. 字体子集重生成(若有新汉字);
  4. 模拟器构建 + 回归脚本(P4 门禁);
  5. 上板 @build + @test;
  6. UI 像素回归通过后再提交。

详见 docs/UI设计/UI_界面制作流程.md 与 docs/UI设计/UI_自动化测试流程.md。

9. 延伸阅读

主题 文档
UI 架构 docs/UI设计/UI_设计架构.md
菜单页面 docs/UI设计/菜单页面设计.md
内容页 docs/UI设计/内容页架构.md
界面制作流程 docs/UI设计/UI_界面制作流程.md
中文字体 docs/UI设计/UI_中文字体生成与配置.md
模拟器部署 docs/UI设计/LVGL模拟器部署与使用说明.md
UI 自动化测试 docs/UI设计/UI_自动化测试流程.md
远程显示协议 docs/UI设计/RemoDispBus协议与接收设计说明.md
模拟器差距 docs/测试说明/模拟器差距清单.md