Files
menu/API.md
2025-12-18 23:56:36 +08:00

16 KiB
Raw Blame History

菜单组件API文档

1. 概述

本文档详细描述了菜单组件的API接口包括核心功能、功能扩展和Modbus映射功能。

2. 核心接口

2.1 上下文管理

/**
 * @brief 获取菜单组件上下文所需的内存大小
 * @return 上下文内存大小(字节)
 */
uint32_t menu_get_ctx_size(void);

/**
 * @brief 菜单组件初始化(必须首先调用)
 * @param ctx 菜单上下文指针(用户需提前分配内存)
 * @return 错误码
 */
MenuErrCode menu_init(MenuGlobalCtx* ctx);

/**
 * @brief 菜单组件反初始化(释放资源)
 * @param ctx 菜单上下文指针
 * @return 错误码
 */
MenuErrCode menu_deinit(MenuGlobalCtx* ctx);

/**
 * @brief 检查菜单组件是否已初始化
 * @param ctx 菜单上下文指针
 * @return 是否已初始化
 */
bool menu_is_initialized(MenuGlobalCtx* ctx);

2.2 菜单管理

/**
 * @brief 注册菜单节点(构建菜单树)
 * @param ctx 菜单上下文指针
 * @param parent_id 父节点ID根节点填0
 * @param node_id 当前节点ID唯一不可重复
 * @param name_str 菜单名称字符串(或多语言索引)
 * @param enter_cb 进入该菜单的回调函数NULL表示无
 * @param exit_cb 退出该菜单的回调函数NULL表示无
 * @return 错误码
 */
MenuErrCode menu_register_node(MenuGlobalCtx* ctx, MenuNodeId parent_id, MenuNodeId node_id, const char* name_str, MenuCallback enter_cb, MenuCallback exit_cb);

/**
 * @brief 批量注册菜单节点
 * @param ctx 菜单上下文指针
 * @param configs 菜单节点配置数组
 * @param config_count 配置数量
 * @return 错误码
 */
MenuErrCode menu_register_nodes(MenuGlobalCtx* ctx, const MenuNodeConfig* configs, uint16_t config_count);

/**
 * @brief 获取当前选中的菜单节点ID
 * @param ctx 菜单上下文指针
 * @param node_id 输出参数当前节点ID
 * @return 错误码
 */
MenuErrCode menu_get_current_node(MenuGlobalCtx* ctx, MenuNodeId* node_id);

2.3 事件处理

/**
 * @brief 发送事件到菜单事件队列(如按键事件、自定义事件)
 * @param ctx 菜单上下文指针
 * @param type 事件类型
 * @param param 事件附加参数(可选,如按键长按时间)
 * @param priority 事件优先级(可选,默认为普通优先级)
 * @return 错误码
 */
MenuErrCode menu_post_event(MenuGlobalCtx* ctx, MenuEventType type, uint32_t param, MenuEventPriority priority);

/**
 * @brief 菜单主循环(需在用户主循环中调用,处理事件和刷新显示)
 * @param ctx 菜单上下文指针
 */
void menu_main_loop(MenuGlobalCtx* ctx);

3. 功能扩展接口

3.1 参数管理

/**
 * @brief 注册参数到菜单节点(参数管理功能)
 * @param ctx 菜单上下文指针
 * @param node_id 菜单节点ID参数与菜单绑定
 * @param param_id 参数ID唯一
 * @param type 参数类型
 * @param min_val 最小值(浮点型,内部自动转换)
 * @param max_val 最大值(浮点型,内部自动转换)
 * @param default_val 默认值(浮点型,内部自动转换)
 * @param scale 缩放因子如0.1表示保留1位小数
 * @return 错误码
 */
MenuErrCode menu_param_register(MenuGlobalCtx* ctx, MenuNodeId node_id, uint16_t param_id, MenuParamType type, float min_val, float max_val, float default_val, float scale);

/**
 * @brief 批量注册参数到菜单节点
 * @param ctx 菜单上下文指针
 * @param configs 参数配置数组
 * @param config_count 配置数量
 * @return 错误码
 */
MenuErrCode menu_param_register_batch(MenuGlobalCtx* ctx, const MenuParamConfig* configs, uint16_t config_count);

/**
 * @brief 设置参数值
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param value 新值(浮点型,内部自动转换)
 * @return 错误码
 */
MenuErrCode menu_param_set_value(MenuGlobalCtx* ctx, uint16_t param_id, float value);

/**
 * @brief 获取参数值
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param value 输出参数,当前值(浮点型)
 * @return 错误码
 */
MenuErrCode menu_param_get_value(MenuGlobalCtx* ctx, uint16_t param_id, float* value);

/**
 * @brief 获取参数类型
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param type 输出参数,参数类型
 * @return 错误码
 */
MenuErrCode menu_param_get_type(MenuGlobalCtx* ctx, uint16_t param_id, MenuParamType* type);

3.2 多语言支持

/**
 * @brief 设置当前语言
 * @param ctx 菜单上下文指针
 * @param lang_id 语言ID如0-中文1-英文)
 * @return 错误码
 */
MenuErrCode menu_lang_set_current(MenuGlobalCtx* ctx, uint8_t lang_id);

/**
 * @brief 获取当前语言
 * @param ctx 菜单上下文指针
 * @param lang_id 输出参数当前语言ID
 * @return 错误码
 */
MenuErrCode menu_lang_get_current(MenuGlobalCtx* ctx, uint8_t* lang_id);

/**
 * @brief 注册语言字符串
 * @param ctx 菜单上下文指针
 * @param str_id 字符串ID
 * @param lang_id 语言ID
 * @param str 语言字符串
 * @return 错误码
 */
MenuErrCode menu_lang_register_str(MenuGlobalCtx* ctx, uint16_t str_id, uint8_t lang_id, const char* str);

/**
 * @brief 批量注册语言字符串
 * @param ctx 菜单上下文指针
 * @param strs 语言字符串数组
 * @param count 字符串数量
 * @return 错误码
 */
MenuErrCode menu_lang_register_strs(MenuGlobalCtx* ctx, const MenuLangStr* strs, uint16_t count);

/**
 * @brief 加载语言包(动态加载语言字符串)
 * @param ctx 菜单上下文指针
 * @param lang_id 语言ID
 * @param strs 语言字符串数组
 * @param count 字符串数量
 * @return 错误码
 */
MenuErrCode menu_lang_load_pack(MenuGlobalCtx* ctx, uint8_t lang_id, const MenuLangStr* strs, uint16_t count);

3.3 内存监控

/**
 * @brief 获取菜单内存使用统计信息
 * @param ctx 菜单上下文指针
 * @param stats 输出参数,内存使用统计信息
 * @return 错误码
 */
MenuErrCode menu_get_mem_stats(MenuGlobalCtx* ctx, MenuMemStats* stats);

4. Modbus映射功能

/**
 * @brief 注册参数与Modbus寄存器的映射关系
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID需已通过menu_param_register注册
 * @param reg_type 寄存器类型
 * @param reg_addr 寄存器起始地址协议地址如40001
 * @param reg_count 占用寄存器数量如1:16位2:32位4:64位
 * @param perm 读写权限
 * @param byte_order 字节序可选默认使用MENU_CONFIG_MODBUS_BYTE_ORDER
 * @return 错误码
 */
MenuErrCode menu_modbus_map_register(MenuGlobalCtx* ctx, uint16_t param_id, ModbusRegType reg_type, uint16_t reg_addr, uint8_t reg_count, ModbusPerm perm, uint8_t byte_order);

/**
 * @brief 批量注册参数与Modbus寄存器的映射关系
 * @param ctx 菜单上下文指针
 * @param configs Modbus映射配置数组
 * @param config_count 配置数量
 * @return 错误码
 */
MenuErrCode menu_modbus_map_register_batch(MenuGlobalCtx* ctx, const MenuModbusMapConfig* configs, uint16_t config_count);

/**
 * @brief 根据参数ID查询Modbus映射关系
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param map 输出参数,映射关系结构体
 * @return 错误码
 */
MenuErrCode menu_modbus_map_query_by_param(MenuGlobalCtx* ctx, uint16_t param_id, ModbusMap* map);

/**
 * @brief 根据寄存器地址和类型查询Modbus映射关系
 * @param ctx 菜单上下文指针
 * @param reg_type 寄存器类型
 * @param reg_addr 寄存器地址
 * @param map 输出参数,映射关系结构体
 * @return 错误码
 */
MenuErrCode menu_modbus_map_query_by_reg(MenuGlobalCtx* ctx, ModbusRegType reg_type, uint16_t reg_addr, ModbusMap* map);

/**
 * @brief 将参数值写入对应的Modbus寄存器双向转换参数值→寄存器数据
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param reg_buf 输出参数寄存器数据缓冲区需足够大如32位占2个16位寄存器
 * @param buf_len 缓冲区长度(输入),实际写入长度(输出)
 * @return 错误码
 */
MenuErrCode menu_modbus_map_param_to_reg(MenuGlobalCtx* ctx, uint16_t param_id, uint8_t* reg_buf, uint8_t* buf_len);

/**
 * @brief 将Modbus寄存器数据读取到参数值双向转换寄存器数据→参数值
 * @param ctx 菜单上下文指针
 * @param param_id 参数ID
 * @param reg_buf 输入参数,寄存器数据缓冲区
 * @param buf_len 缓冲区长度
 * @return 错误码
 */
MenuErrCode menu_modbus_map_reg_to_param(MenuGlobalCtx* ctx, uint16_t param_id, const uint8_t* reg_buf, uint8_t buf_len);

5. 数据类型

5.1 错误码

typedef enum {
    MENU_OK = 0,                ///< 操作成功
    MENU_ERR_INVALID_PARAM,     ///< 无效参数
    MENU_ERR_OUT_OF_MEMORY,     ///< 内存不足(静态内存池已满)
    MENU_ERR_NODE_NOT_FOUND,    ///< 菜单节点未找到
    MENU_ERR_STACK_OVERFLOW,    ///< 菜单栈溢出(导航层级超过配置)
    MENU_ERR_STACK_UNDERFLOW,   ///< 菜单栈下溢(已到根节点仍返回)
    MENU_ERR_EVENT_QUEUE_FULL,  ///< 事件队列已满
    MENU_ERR_NOT_SUPPORTED,     ///< 功能未启用(如未开启多语言)
    MENU_ERR_HW_PORT_ERROR,     ///< 硬件端口层错误
    MENU_ERR_NOT_INITIALIZED,   ///< 组件未初始化
    MENU_ERR_INVALID_CONTEXT     ///< 无效上下文指针
} MenuErrCode;

5.2 事件类型

typedef enum {
    MENU_EVENT_NONE = 0,        ///< 无事件
    MENU_EVENT_KEY_UP,          ///< 上键按下
    MENU_EVENT_KEY_DOWN,        ///< 下键按下
    MENU_EVENT_KEY_ENTER,       ///< 确认键按下
    MENU_EVENT_KEY_BACK,        ///< 返回键按下
    MENU_EVENT_CUSTOM_BEGIN = 0x10, ///< 自定义事件起始标识(用户可扩展)
} MenuEventType;

5.3 事件优先级

typedef enum {
    MENU_EVENT_PRIORITY_LOW = 0,    ///< 低优先级事件
    MENU_EVENT_PRIORITY_NORMAL,     ///< 普通优先级事件(默认)
    MENU_EVENT_PRIORITY_HIGH,       ///< 高优先级事件
    MENU_EVENT_PRIORITY_CRITICAL    ///< 紧急优先级事件
} MenuEventPriority;

5.4 参数类型

typedef enum {
    MENU_PARAM_TYPE_INT8,
    MENU_PARAM_TYPE_UINT8,
    MENU_PARAM_TYPE_INT16,
    MENU_PARAM_TYPE_UINT16,
    MENU_PARAM_TYPE_INT32,
    MENU_PARAM_TYPE_UINT32,
    MENU_PARAM_TYPE_FLOAT,
} MenuParamType;

5.5 菜单状态

typedef enum {
    MENU_STATE_INIT = 0,         ///< 初始化状态
    MENU_STATE_NORMAL,           ///< 正常导航状态
    MENU_STATE_PARAM_EDIT,       ///< 参数编辑状态
    MENU_STATE_CONFIRM,          ///< 确认状态(如保存/退出确认)
    MENU_STATE_ERROR,            ///< 错误状态
} MenuState;

6. 配置项

菜单组件的配置项位于menu_config.h文件中,用户可以根据项目需求调整以下配置:

6.1 核心配置

  • MENU_CONFIG_MAX_NODES:最大菜单节点数
  • MENU_CONFIG_STACK_DEPTH:菜单栈深度
  • MENU_CONFIG_EVENT_QUEUE_LEN:事件队列长度
  • MENU_CONFIG_ENABLE_ASSERT:是否启用断言
  • MENU_CONFIG_ENABLE_DEBUG:是否启用调试打印
  • MENU_CONFIG_ENABLE_MEM_MONITOR:是否启用内存监控

6.2 功能扩展配置

  • MENU_CONFIG_ENABLE_PARAM:是否启用参数管理功能
  • MENU_CONFIG_ENABLE_LANG:是否启用多语言功能
  • MENU_CONFIG_MAX_PARAMS:最大参数数量
  • MENU_CONFIG_MAX_LANGS:支持的最大语言数量

6.3 Modbus映射配置

  • MENU_CONFIG_ENABLE_MODBUS_MAP:是否启用参数-Modbus寄存器映射功能
  • MENU_CONFIG_MAX_MODBUS_MAPS最大Modbus映射数量
  • MENU_CONFIG_MODBUS_MAX_ADDRModbus寄存器地址最大值
  • MENU_CONFIG_MODBUS_BYTE_ORDER默认Modbus字节序
  • MENU_CONFIG_MODBUS_PERMISSION是否启用Modbus映射权限校验

7. 硬件适配

菜单组件的硬件适配层位于port/menu_port.hport/menu_port.c文件中,用户需要实现以下接口:

/**
 * @brief 硬件端口驱动结构体(模块化设计,支持运行时配置)
 */
typedef struct {
    void (*printf)(const char* fmt, va_list args);      ///< 硬件打印接口
    uint32_t (*get_tick)(void);                        ///< 获取系统滴答时间
    void (*delay_ms)(uint32_t ms);                     ///< 硬件延迟函数
    void (*display)(const char* menu_name, uint16_t menu_id); ///< 菜单显示接口
    MenuEventType (*key_scan)(void);                  ///< 按键扫描接口(可选)
    void (*irq_ctrl)(bool enable);                    ///< 中断管理接口(可选)
    void (*error_handler)(MenuErrCode err_code);      ///< 错误处理接口(可选)
    MenuErrCode (*modbus_send)(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len); ///< Modbus发送接口可选
    MenuErrCode (*modbus_receive)(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len); ///< Modbus接收接口可选
} MenuPortDriver;

/**
 * @brief 硬件端口初始化接口
 * @param driver 硬件驱动结构体指针
 * @return 错误码
 */
MenuErrCode menu_port_init(const MenuPortDriver* driver);

/**
 * @brief 硬件端口反初始化接口
 * @return 错误码
 */
MenuErrCode menu_port_deinit(void);

8. 使用示例

8.1 基本使用

#include "menu.h"
#include "menu_port.h"

int main(void)
{
    // 1. 初始化硬件
    hal_init();
    
    // 2. 初始化菜单上下文
    uint8_t menu_ctx_buf[menu_get_ctx_size()];
    MenuGlobalCtx* ctx = (MenuGlobalCtx*)menu_ctx_buf;
    menu_init(ctx);
    
    // 3. 注册菜单节点
    menu_register_node(ctx, 0, 1, "主菜单", NULL, NULL);
    menu_register_node(ctx, 1, 2, "参数设置", NULL, NULL);
    menu_register_node(ctx, 1, 3, "系统信息", NULL, NULL);
    
    // 4. 主循环
    while (1)
    {
        // 扫描按键
        MenuEventType key_event = scan_key();
        if (key_event != MENU_EVENT_NONE)
        {
            menu_post_event(ctx, key_event, 0, MENU_EVENT_PRIORITY_NORMAL);
        }
        
        // 处理菜单事件
        menu_main_loop(ctx);
        
        // 其他业务逻辑
        // ...
    }
    
    // 5. 反初始化
    menu_deinit(ctx);
    
    return 0;
}

8.2 批量注册菜单节点

// 定义菜单节点配置
MenuNodeConfig menu_nodes[] = {
    {1, 0, "主菜单", NULL, NULL},
    {2, 1, "参数设置", NULL, NULL},
    {3, 1, "系统信息", NULL, NULL},
    {4, 2, "温度参数", NULL, NULL},
    {5, 2, "湿度参数", NULL, NULL}
};

// 批量注册菜单节点
menu_register_nodes(ctx, menu_nodes, sizeof(menu_nodes) / sizeof(menu_nodes[0]));

8.3 参数管理

// 注册参数
menu_param_register(ctx, 4, 1, MENU_PARAM_TYPE_FLOAT, 0.0f, 100.0f, 25.0f, 1.0f);

// 设置参数值
menu_param_set_value(ctx, 1, 30.0f);

// 获取参数值
float value;
menu_param_get_value(ctx, 1, &value);

8.4 多语言支持

// 注册语言字符串
menu_lang_register_str(ctx, 1, 0, "中文菜单");
menu_lang_register_str(ctx, 1, 1, "English Menu");

// 设置当前语言为中文
menu_lang_set_current(ctx, 0);

// 动态加载语言包
MenuLangStr lang_pack[] = {
    {2, 0, "中文参数"},
    {2, 1, "English Param"},
    {3, 0, "中文信息"},
    {3, 1, "English Info"}
};
menu_lang_load_pack(ctx, 0, lang_pack, sizeof(lang_pack) / sizeof(lang_pack[0]));

8.5 Modbus映射

// 注册Modbus映射
menu_modbus_map_register(ctx, 1, MODBUS_REG_TYPE_HOLDING_REG, 40001, 2, MODBUS_PERM_READ_WRITE, 2);

// 参数值转换为Modbus寄存器数据
uint8_t reg_buf[4];
uint8_t buf_len = sizeof(reg_buf);
menu_modbus_map_param_to_reg(ctx, 1, reg_buf, &buf_len);

// Modbus寄存器数据转换为参数值
menu_modbus_map_reg_to_param(ctx, 1, reg_buf, buf_len);

9. 版本信息

  • 版本v1.0.0
  • 最后更新2025-12-18
  • 适用平台所有支持C语言的嵌入式系统