# 工业级嵌入式菜单组件 ## 1. 项目概述 本项目是一个基于C语言开发的工业级嵌入式菜单组件,设计用于资源受限的嵌入式系统,具有高可移植性、模块化、可裁剪、低资源占用和事件驱动解耦等核心特点。 ### 1.1 核心特性 - **分层架构设计**:核心层 + 功能扩展层 + 硬件端口层,彻底解耦硬件与业务逻辑 - **事件驱动机制**:基于事件队列的异步处理,提高系统响应性 - **静态内存管理**:完全使用静态数组,避免内存碎片,适合资源受限系统 - **高度可配置**:通过宏开关实现功能裁剪,可根据项目需求定制功能 - **工业级鲁棒性**:完善的边界检查、错误处理和断言机制 - **Modbus映射支持**:内置参数与Modbus寄存器双向映射功能 ## 2. 目录结构 ``` menu/ ├── api/ # 对外API层(用户唯一需要引用的头文件) │ ├── menu.h # 主接口头文件 │ └── menu_config.h # 配置文件(功能开关、资源大小) ├── internal/ # 内部头文件层(用户无需关心) │ ├── menu_core.h # 核心类型定义 │ ├── menu_data.h # 共享全局变量声明 │ ├── menu_def.h # 内部宏和辅助函数 │ └── menu_modbus.h # Modbus映射内部定义 ├── port/ # 硬件端口层(用户需适配) │ ├── menu_port.c # 硬件接口实现(示例) │ └── menu_port.h # 硬件接口声明 ├── src/ # 源码层 │ ├── core/ # 核心逻辑 │ │ └── menu_core.c # 导航、栈管理、主循环 │ ├── features/ # 功能扩展 │ │ └── menu_modbus.c # Modbus映射功能 │ ├── lang/ # 多语言支持 │ │ └── menu_lang.c # 语言切换、字符串管理 │ ├── param/ # 参数管理 │ │ └── menu_param.c # 参数注册、读写、范围检查 │ └── utils/ # 工具函数 │ └── menu_utils.c # 调试打印、断言、系统滴答 └── examples/ # 示例代码 └── menu_example.c # 菜单组件使用示例 ``` ## 3. 核心功能说明 ### 3.1 菜单导航 - 支持多级菜单导航(上下键切换,确认键进入,返回键退出) - 环形导航(到达边界自动循环) - 菜单栈管理,支持深度导航 ### 3.2 参数管理 - 支持多种参数类型(int8/uint8/int16/uint16/int32/uint32/float) - 自动范围检查和边界处理 - 参数与菜单节点绑定,支持菜单直接调整参数 - 默认值恢复功能 ### 3.3 多语言支持 - 支持多种语言切换 - 字符串ID映射机制 - 自动回退到默认语言 ### 3.4 Modbus映射 - 参数与Modbus寄存器双向映射 - 支持多种Modbus寄存器类型(线圈、离散输入、保持寄存器、输入寄存器) - 灵活的读写权限控制 - 支持多种字节序(小端、大端、Modbus标准) - 自动类型转换和边界检查 ## 4. 快速开始 ### 4.1 配置组件 在`menu_config.h`中根据项目需求配置功能开关和资源大小: ```c // 核心配置 #define MENU_CONFIG_MAX_NODES 32 // 最大菜单节点数 #define MENU_CONFIG_STACK_DEPTH 8 // 菜单栈深度 #define MENU_CONFIG_EVENT_QUEUE_LEN 16 // 事件队列长度 // 功能扩展配置 #define MENU_CONFIG_ENABLE_PARAM 1 // 启用参数管理功能 #define MENU_CONFIG_ENABLE_LANG 1 // 启用多语言功能 #define MENU_CONFIG_ENABLE_MODBUS_MAP 1 // 启用Modbus映射功能 // Modbus映射配置 #define MENU_CONFIG_MAX_MODBUS_MAPS 16 // 最大Modbus映射数量 #define MENU_CONFIG_MODBUS_BYTE_ORDER 2 // 默认Modbus字节序 ``` ### 4.2 适配硬件端口 在`port/menu_port.c`中实现硬件相关接口: ```c // 禁用/启用全局中断 void menu_port_irq_disable(void) { // 实现禁用中断的逻辑 } void menu_port_irq_enable(void) { // 实现启用中断的逻辑 } // 获取系统滴答时间(ms) uint32_t menu_port_get_tick(void) { // 实现获取系统时间的逻辑 return HAL_GetTick(); // 示例:STM32 HAL库 } // 调试打印接口 void menu_port_printf(const char* fmt, va_list args) { // 实现打印逻辑,如通过UART输出 vprintf(fmt, args); } ``` ### 4.3 基本使用示例 ```c #include "menu.h" #include "menu_port.h" // 菜单回调函数 static MenuErrCode menu_cb_enter_param(MenuNodeId node_id) { MENU_DEBUG("Enter param menu: %d", node_id); return MENU_OK; } int main(void) { // 1. 初始化硬件(UART、LCD、SysTick等) hal_init(); // 2. 初始化菜单组件 menu_init(); // 3. 注册菜单节点 menu_register_node(0, 1, "主菜单", NULL, NULL); // 根节点 menu_register_node(1, 2, "参数设置", menu_cb_enter_param, NULL); // 子节点 menu_register_node(1, 3, "系统信息", NULL, NULL); // 子节点 menu_register_node(2, 4, "温度设置", NULL, NULL); // 孙节点 // 4. 注册参数(可选) #if MENU_CONFIG_ENABLE_PARAM menu_param_register(4, 1, MENU_PARAM_TYPE_FLOAT, 0.0f, 100.0f, 25.0f, 1.0f); #endif // 5. 注册Modbus映射(可选) #if MENU_CONFIG_ENABLE_MODBUS_MAP menu_modbus_map_register(1, MODBUS_REG_TYPE_HOLDING_REG, 40001, 2, MODBUS_PERM_READ_WRITE, 2); #endif // 6. 主循环 while (1) { // 扫描硬件按键 menu_port_key_scan(); // 处理菜单事件和刷新显示 menu_main_loop(); // 其他业务逻辑 // ... } } ``` ## 5. Modbus映射功能详解 ### 5.1 核心概念 Modbus映射功能实现了菜单参数与Modbus寄存器的双向数据转换,支持: - **参数到寄存器**:将菜单参数值转换为Modbus寄存器数据 - **寄存器到参数**:将Modbus寄存器数据转换为菜单参数值 - **自动类型转换**:支持不同数据类型之间的自动转换 - **字节序适配**:支持多种字节序,兼容不同Modbus设备 ### 5.2 寄存器类型支持 | 寄存器类型 | 地址范围 | 读写特性 | 支持的参数类型 | |-----------|---------|---------|--------------| | 线圈 | 00001-09999 | 读写 | INT8、UINT8 | | 离散输入 | 10001-19999 | 只读 | INT8、UINT8 | | 输入寄存器 | 30001-39999 | 只读 | 所有类型 | | 保持寄存器 | 40001-49999 | 读写 | 所有类型 | ### 5.3 字节序支持 | 字节序类型 | 值 | 描述 | |-----------|-----|------| | 小端 | 0 | 低字节在前,高字节在后(x86架构默认) | | 大端 | 1 | 高字节在前,低字节在后 | | Modbus标准 | 2 | 字小端,字节大端(Modbus协议默认) | ### 5.4 Modbus映射使用示例 ```c // 1. 注册参数(必须在映射之前完成) menu_param_register(menu_node_id, param_id, MENU_PARAM_TYPE_FLOAT, 0.0f, 100.0f, 25.0f, 1.0f); // 2. 注册Modbus映射 menu_modbus_map_register( param_id, // 参数ID MODBUS_REG_TYPE_HOLDING_REG, // 寄存器类型 40001, // 起始地址 2, // 寄存器数量(浮点型占2个16位寄存器) MODBUS_PERM_READ_WRITE, // 读写权限 2 // 字节序(Modbus标准) ); // 3. 参数到寄存器转换 uint8_t reg_buf[4] = {0}; uint8_t buf_len = sizeof(reg_buf); menu_modbus_map_param_to_reg(param_id, reg_buf, &buf_len); // 4. 寄存器到参数转换 const uint8_t reg_data[4] = {0x00, 0x00, 0x4B, 0x40}; // 25.0f的二进制表示 menu_modbus_map_reg_to_param(param_id, reg_data, sizeof(reg_data)); ``` ## 6. 配置说明 ### 6.1 核心配置项 | 配置项 | 说明 | 默认值 | |-------|------|-------| | MENU_CONFIG_MAX_NODES | 最大菜单节点数 | 32 | | MENU_CONFIG_STACK_DEPTH | 菜单栈深度 | 8 | | MENU_CONFIG_EVENT_QUEUE_LEN | 事件队列长度 | 16 | | MENU_CONFIG_ENABLE_ASSERT | 是否启用断言 | 1 | | MENU_CONFIG_ENABLE_DEBUG | 是否启用调试打印 | 1 | ### 6.2 功能扩展配置 | 配置项 | 说明 | 默认值 | |-------|------|-------| | MENU_CONFIG_ENABLE_PARAM | 是否启用参数管理 | 1 | | MENU_CONFIG_ENABLE_LANG | 是否启用多语言支持 | 1 | | MENU_CONFIG_ENABLE_MODBUS_MAP | 是否启用Modbus映射 | 1 | ### 6.3 Modbus映射配置 | 配置项 | 说明 | 默认值 | |-------|------|-------| | MENU_CONFIG_MAX_MODBUS_MAPS | 最大Modbus映射数量 | 16 | | MENU_CONFIG_MODBUS_MAX_ADDR | Modbus寄存器地址最大值 | 0xFFFF | | MENU_CONFIG_MODBUS_BYTE_ORDER | 默认Modbus字节序 | 2(Modbus标准) | | MENU_CONFIG_MODBUS_PERMISSION | 是否启用权限校验 | 1 | ## 7. 移植指南 ### 7.1 硬件端口层适配 用户只需适配`port/menu_port.c`中的以下接口: 1. **中断管理**:`menu_port_irq_disable()`、`menu_port_irq_enable()` 2. **系统时间**:`menu_port_get_tick()` 3. **调试打印**:`menu_port_printf()` 4. **错误处理**:`menu_port_error_handler()` 5. **按键扫描**:`menu_port_key_scan()`(可选,用户也可以在外部实现) 6. **显示接口**:`menu_port_display()`(可选) ### 7.2 编译配置 1. 将`menu/api`目录添加到Include路径 2. 根据项目需求配置`menu_config.h` 3. 编译时包含所有必要的源文件 ## 8. 性能与资源占用 ### 8.1 内存占用 - **Flash占用**:约5-15KB(取决于启用的功能) - **RAM占用**:约1-3KB(取决于配置的节点数、参数数和Modbus映射数) ### 8.2 执行效率 - 事件处理:单次事件处理时间 < 10μs - 菜单刷新:单次刷新时间 < 5μs - 参数转换:单次转换时间 < 2μs - Modbus映射:单次映射转换时间 < 5μs ## 9. 工业级设计考量 1. **无动态内存分配**:完全使用静态数组,避免内存碎片 2. **事件驱动设计**:硬件与软件解耦,提高系统响应性 3. **完善的错误处理**:每个函数都有明确的错误码返回 4. **边界检查**:所有数组访问都有边界检查,防止越界 5. **断言机制**:关键函数入口有断言检查,便于调试 6. **可配置裁剪**:通过宏开关可以裁剪不需要的功能 7. **模块化设计**:各功能模块独立,便于维护和扩展 ## 10. 应用场景 - 工业控制器 - 智能家居设备 - 仪器仪表 - 医疗设备 - 嵌入式人机界面 - Modbus从站设备 ## 11. 许可证 本项目采用MIT许可证,可自由用于商业和非商业项目。 ## 12. 联系方式 如有问题或建议,欢迎提交Issue或Pull Request。 --- **版本信息**:v1.0.0 **最后更新**:2025-12-18 **适用平台**:所有支持C语言的嵌入式系统