2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 22:24:25 +08:00
2025-12-18 21:24:20 +08:00
2025-12-18 21:24:20 +08:00

工业级嵌入式菜单组件

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中根据项目需求配置功能开关和资源大小:

// 核心配置
#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中实现硬件相关接口:

// 禁用/启用全局中断
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 基本使用示例

#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映射使用示例

// 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字节序 2Modbus标准
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语言的嵌入式系统

Description
No description provided
Readme 303 KiB
Languages
C 99.3%
CMake 0.7%