# PC_HMI – 本地 HMI 菜单逻辑的 PC 端模拟 本目录提供一个 **纯 C 语言的控制台程序**,在 PC 上模拟嵌入式 HMI 的菜单交互逻辑,方便调试和理解 `Menu_Route` / `Menu_Show_Proc` 的行为。 ## 环境搭建 ### 1. 安装 CMake 1. 访问 CMake 官网下载页:[`https://cmake.org/download/`](https://cmake.org/download/) 2. 下载适用于 Windows 的安装包(通常为 `cmake-*-windows-x86_64.msi`),安装时**勾选将 CMake 添加到 PATH**。 3. 安装完成后打开终端(PowerShell / CMD),执行: ```powershell cmake --version ``` 能看到版本信息即表示安装成功。 ### 2. 编译器与编码说明 - Windows 下默认使用 **Visual Studio / MSVC** 工具链进行编译。 - 源文件采用 **UTF‑8 编码并包含中文注释**,`CMakeLists.txt` 中已经为 MSVC 打开 `/utf-8` 选项,无需额外配置即可正常编译。 ## 目录结构 - `CMakeLists.txt` – CMake 构建配置 - `include/menu.h` – 菜单数据结构与接口声明 - `include/tcp.h` – TCP 通信接口(客户端/服务端) - `src/menu.c` – 简单菜单树与菜单调度逻辑(PC 版) - `src/main.c` – 主程序入口,从键盘读取按键并驱动菜单 - `src/tcp.c` – TCP 实现(Windows Winsock / Linux socket) ## 构建步骤 ### 1. Windows 示例(当前工程默认方式) 在仓库根目录下执行(注意路径中有空格时要加引号): ```powershell mkdir build cd "D:\Code\DTU 程序\DTU-HMI\build" cmake .. cmake --build . ``` ### 2. 通用(Linux / macOS 等) ```bash mkdir build cd build cmake ../ cmake --build . ``` 生成的可执行文件名为: ```text pc_hmi # Windows / Linux 下均可 ``` ## 运行与按键映射 ```bash ./pc_hmi ``` 在控制台中使用以下按键进行菜单操作: - `W` / `w` – 上(对应嵌入式的 `CN_KEY_U`) - `S` / `s` – 下(`CN_KEY_D`) - `A` / `a` – 左(`CN_KEY_L`) - `D` / `d` – 右(`CN_KEY_R`) - `Enter` – 确认 / 进入子菜单(`CN_KEY_ENT`) - `Esc` – 返回上一级(`CN_KEY_ESC`) 界面中会用 `[*名称*]` 标出当前选中的菜单项,并在底部显示对应的提示信息。 > 注意:当前只是一个 **最小化演示环境**,菜单树结构与嵌入式工程中的 `g_tMenuModelTab` 不完全一致,但交互方式相仿,可作为移植和调试时的参考。 ## TCP 通信 项目已集成 **跨平台 TCP 模块**(`include/tcp.h` + `src/tcp.c`),可用于与设备或上位机进行 TCP 通信。 - **Windows**:使用 Winsock2,已自动链接 `ws2_32`。 - **Linux**:使用 BSD socket,无需额外库。 ### 使用前初始化 程序入口已调用 `Tcp_Init()`,退出前会调用 `Tcp_Cleanup()`。若在其它线程或模块中使用 TCP,无需重复初始化。 ### TCP 客户端示例 ```c #include "../include/tcp.h" /* 连接服务器 */ int sock = TcpClient_Connect("192.168.1.100", 502); if (sock == TCP_INVALID_SOCKET) { /* 连接失败 */ return; } /* 发送数据 */ const char *msg = "hello"; int sent = TcpClient_Send(sock, msg, strlen(msg)); /* 接收数据 */ char buf[256]; int n = TcpClient_Recv(sock, buf, sizeof(buf) - 1); if (n > 0) { buf[n] = '\0'; printf("recv: %s\n", buf); } /* 关闭连接 */ TcpClient_Close(sock); ``` ### TCP 服务端示例 ```c int server = TcpServer_Listen(8080); if (server == TCP_INVALID_SOCKET) return; int client = TcpServer_Accept(server); /* 阻塞等待客户端 */ if (client != TCP_INVALID_SOCKET) { TcpClient_Send(client, "welcome", 7); TcpClient_Close(client); } TcpServer_Close(server); ``` 接口说明见 `include/tcp.h`。