# 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. 系统分层架构 ```text +----------------------+ | 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` ### 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 主循环流程 ```text [系统初始化] | 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 远程显示协议流程 ```text [Accept客户端] | v [接收缓冲区累积] | v [parse_frame 校验解析] | +--成功--------> [按 cmd 分发] --> [send_reply 回包] --> [接收缓冲区累积] | +--失败/不完整--> [接收缓冲区累积] ``` 命令语义(RemoDispBus): - `CMD_INIT`:返回 LCD 宽高与显存尺寸 - `CMD_LCDMEM`:返回显存数据(支持起始地址) - `CMD_KEY`:注入远程按键到 `g_tRemoteKey` - `CMD_KEEPLIVE`:保活响应 ## 7. 并发与线程模型 - 主线程: - 负责菜单路由与本地显示刷新 - TCP 服务器线程: - 监听连接、解析协议、处理远程请求 共享状态: - `g_tCVsr.pwbyLCDMemory`(远程读取 + 本地写入) - `g_tRemoteKey`(远程写入 + 菜单读取) 当前实现未使用锁机制,依赖业务访问模式降低冲突风险。 后续若并发复杂度提升,建议引入细粒度互斥或无锁缓冲策略。 ## 8. 构建与运行架构 - 构建系统:CMake(`C_STANDARD 99`) - 可执行目标:`DTU-HMI` - 平台链接: - Windows:`ws2_32` - Linux/macOS:`pthread` - 可选调试:`ENABLE_DEBUG=ON` 自动定义 `DEBUG` 宏 ## 9. 测试架构 测试目录:`tests/` - 框架:`ctest + 自定义断言宏` - 分层策略: - P0:纯逻辑单元测试(协议解析、UTF-8 解析、字库查找) - P1:状态/计算单测(按键、菜单、LCD 基础像素操作) - P2:集成测试(TCP 回环) 建议执行命令: ```bash cmake -S . -B build cmake --build build ctest --test-dir build -C Debug --output-on-failure ``` ## 10. 模块依赖关系(代码级) - `main.c` 依赖:`menu`、`key`、`remoteDisplay`、`tcp`、`thread_utils` - `menu.c` 依赖:`lcd`、`display`、`key` - `remoteDisplay.c` 依赖:`lcd`、`key`、`tcp`、`thread_utils` - `lcd.c` 依赖:`ascii` - `display.c` 提供:静态菜单表(被 `menu.c` 使用) ## 11. 已知风险与改进建议 - **并发一致性风险**:远程线程与主线程共享状态无锁访问。 - 建议:为显存快照与按键事件引入互斥保护或双缓冲。 - **协议缓冲鲁棒性**:当前异常数据采用清空缓冲策略,存在丢包窗口。 - 建议:增加更精细的帧边界恢复策略与统计日志。 - **可测试性边界**:部分逻辑仍与全局状态耦合较深。 - 建议:逐步引入接口注入(如 `TcpOps`、`delay_ms`)降低耦合。 ## 12. 版本与维护 - 文档版本:v1.0 - 适配代码基线:当前 `DTU-HMI` 仓库主干实现 - 维护建议: - 每次新增模块或调整主流程时同步更新本文档 - 测试策略更新需同步维护“第 9 章 测试架构”