7.6 KiB
7.6 KiB
DTU-HMI 系统架构设计文档
1. 文档目的
本文档用于描述 DTU-HMI 工程的整体架构、核心模块职责、关键数据流、线程与通信模型、构建与测试体系,作为后续开发、联调、测试与维护的统一基线。
2. 系统概述
DTU-HMI 是一个基于纯 C 实现的 PC 端 HMI 菜单逻辑模拟系统,目标是复现现场 DTU 设备的人机界面行为。
系统支持本地菜单交互与远程显示协议(RemoDispBus)通信,主要包含:
- 菜单树构建与路由(多级菜单、同级循环导航)
- LCD 显存与绘制(160x160 单色像素缓冲)
- 按键输入(本地/远程按键注入)
- TCP 服务(远程显示数据交互)
- 跨平台线程与网络适配(Windows/Linux)
3. 架构目标与设计原则
- 可移植性:通过
tcp.c、thread_utils.c封装平台差异。 - 可维护性:按模块职责划分(菜单/显示/网络/线程/输入)。
- 可测试性:优先抽取并覆盖纯逻辑函数,逐步推进集成测试。
- 低耦合高内聚:上层业务通过明确接口调用下层能力。
4. 系统分层架构
+----------------------+
| AppLayer |
| main.c |
+----------+-----------+
|
+--------------+--------------+
| |
v v
+---------+----------+ +---------+------------------+
| MenuLayer | | RemoteDisplayLayer |
| menu.c | | remoteDisplay.c |
+----+-----------+---+ +-----+-----------+----------+
| | | |
v v v v
+------+-----+ +--+---------+ +---+----+ +---+------------------+
|DisplayLayer| |InputLayer | |Input | |PlatformLayer |
|lcd/Ascii/ | |key.c | |key.c | |tcp.c + thread_utils.c |
|display.c | +------------+ +-------+ +------------------------+
+------------+
4.1 应用层
- 文件:
src/main.c - 职责:
- 系统初始化(菜单、按键、TCP 线程)
- 主循环调度(菜单路由、周期显示刷新)
- 生命周期管理(线程退出、网络清理)
4.2 菜单业务层
- 文件:
src/Drv/menu.c、src/Drv/menu.h - 职责:
- 基于静态菜单模型构建运行时菜单树
- 处理按键驱动的菜单状态迁移
- 执行菜单显示坐标计算与多级菜单渲染调度
4.3 显示层
- 文件:
src/Drv/lcd/lcd.c、src/Drv/lcd/lcd_draw.c、src/Drv/lcd/lcd_text.c、src/Drv/lcd/text_codec.c、src/Drv/lcd/ascii.c、src/Drv/display.c - 职责:
- 管理 LCD 显存
g_tCVsr与像素绘制 - 提供 ASCII/UTF-8 字符显示能力
- 提供静态菜单模型定义
g_tMenuModelTab
- 管理 LCD 显存
4.4 输入层
- 文件:
src/Drv/key.c、src/Drv/key.h - 职责:
- 提供按键读写状态控制(消费式读取)
- 接收远程模块写入的按键事件并供菜单模块读取
4.5 远程显示通信层
- 文件:
src/remoteDisplay.c、src/remoteDisplay.h - 职责:
- 实现 RemoDispBus 协议解析与回复
- 提供 TCP 服务器线程入口与启动逻辑
- 处理保活、初始化、按键下发、显存上传等命令
4.6 平台适配层
- 文件:
src/TCP/tcp.c、src/thread_utils.c - 职责:
- 提供跨平台 socket 与线程封装
- 隔离 Windows/Linux API 差异
5. 核心数据结构设计
5.1 菜单模型与菜单树
- 静态菜单模型:
tagMenuModel(定义于display.h,数据在display.c) - 运行时菜单项:
tagMenuItem(定义于menu.c内) - 全局控制:
g_tMenuCtrl、g_tDspCtrl
关键关系:
ptHigher/ptLower:父子层级关系ptBefore/ptBehind:同级双向关系(首尾成环)ptRoute[]:当前路径缓存(0~3 级)
5.2 显示控制结构
tagScreenControl g_tCVsr:- 显存缓冲
pwbyLCDMemory - 前景/背景色
- ASCII 与汉字字体参数
- 显存缓冲
5.3 远程按键结构
tagRKeyCtrl g_tRemoteKey:byKeyValid:是否有新按键byKeyValue:按键值bUseRkey:远程按键开关(当前实现中初始化为启用)
6. 关键业务流程
6.1 主循环流程
[系统初始化]
|
v
[Menu_Route]
|
v
[Sleep 20ms]
|
v
[计数器累加]
|
v
[是否到刷新周期?] --否--> [Menu_Route]
|
+--是--> [Menu_Show_Proc] --> [Menu_Route]
6.2 菜单交互流程
- 输入来源:
Key_Read()(含远程写入按键) - 行为:
- 上/下:同级循环移动
- 左/ESC:回退上级或退回主层
- 右/确认:进入子级或执行叶子回调
- 渲染:
Menu_Show_Proc根据路径增量刷新或全量刷新
6.3 远程显示协议流程
[Accept客户端]
|
v
[接收缓冲区累积]
|
v
[parse_frame 校验解析]
|
+--成功--------> [按 cmd 分发] --> [send_reply 回包] --> [接收缓冲区累积]
|
+--失败/不完整--> [接收缓冲区累积]
命令语义(RemoDispBus):
CMD_INIT:返回 LCD 宽高与显存尺寸CMD_LCDMEM:返回显存数据(支持起始地址)CMD_KEY:注入远程按键到g_tRemoteKeyCMD_KEEPLIVE:保活响应
7. 并发与线程模型
- 主线程:
- 负责菜单路由与本地显示刷新
- TCP 服务器线程:
- 监听连接、解析协议、处理远程请求
共享状态:
g_tCVsr.pwbyLCDMemory(远程读取 + 本地写入)g_tRemoteKey(远程写入 + 菜单读取)
当前实现未使用锁机制,依赖业务访问模式降低冲突风险。
后续若并发复杂度提升,建议引入细粒度互斥或无锁缓冲策略。
8. 构建与运行架构
- 构建系统:CMake(
C_STANDARD 99) - 可执行目标:
DTU-HMI - 平台链接:
- Windows:
ws2_32 - Linux/macOS:
pthread
- Windows:
- 可选调试:
ENABLE_DEBUG=ON自动定义DEBUG宏
9. 测试架构
测试目录:tests/
- 框架:
ctest + 自定义断言宏 - 分层策略:
- P0:纯逻辑单元测试(协议解析、UTF-8 解析、字库查找)
- P1:状态/计算单测(按键、菜单、LCD 基础像素操作)
- P2:集成测试(TCP 回环)
建议执行命令:
cmake -S . -B build
cmake --build build
ctest --test-dir build -C Debug --output-on-failure
10. 模块依赖关系(代码级)
main.c依赖:menu、key、remoteDisplay、tcp、thread_utilsmenu.c依赖:lcd、display、keyremoteDisplay.c依赖:lcd、key、tcp、thread_utilslcd.c依赖:asciidisplay.c提供:静态菜单表(被menu.c使用)
11. 已知风险与改进建议
- 并发一致性风险:远程线程与主线程共享状态无锁访问。
- 建议:为显存快照与按键事件引入互斥保护或双缓冲。
- 协议缓冲鲁棒性:当前异常数据采用清空缓冲策略,存在丢包窗口。
- 建议:增加更精细的帧边界恢复策略与统计日志。
- 可测试性边界:部分逻辑仍与全局状态耦合较深。
- 建议:逐步引入接口注入(如
TcpOps、delay_ms)降低耦合。
- 建议:逐步引入接口注入(如
12. 版本与维护
- 文档版本:v1.0
- 适配代码基线:当前
DTU-HMI仓库主干实现 - 维护建议:
- 每次新增模块或调整主流程时同步更新本文档
- 测试策略更新需同步维护“第 9 章 测试架构”