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

524 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 菜单组件API文档
## 1. 概述
本文档详细描述了菜单组件的API接口包括核心功能、功能扩展和Modbus映射功能。
## 2. 核心接口
### 2.1 上下文管理
```c
/**
* @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 菜单管理
```c
/**
* @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 事件处理
```c
/**
* @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 参数管理
```c
/**
* @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 多语言支持
```c
/**
* @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 内存监控
```c
/**
* @brief 获取菜单内存使用统计信息
* @param ctx 菜单上下文指针
* @param stats 输出参数,内存使用统计信息
* @return 错误码
*/
MenuErrCode menu_get_mem_stats(MenuGlobalCtx* ctx, MenuMemStats* stats);
```
## 4. Modbus映射功能
```c
/**
* @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 错误码
```c
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 事件类型
```c
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 事件优先级
```c
typedef enum {
MENU_EVENT_PRIORITY_LOW = 0, ///< 低优先级事件
MENU_EVENT_PRIORITY_NORMAL, ///< 普通优先级事件(默认)
MENU_EVENT_PRIORITY_HIGH, ///< 高优先级事件
MENU_EVENT_PRIORITY_CRITICAL ///< 紧急优先级事件
} MenuEventPriority;
```
### 5.4 参数类型
```c
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 菜单状态
```c
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_ADDR`Modbus寄存器地址最大值
- `MENU_CONFIG_MODBUS_BYTE_ORDER`默认Modbus字节序
- `MENU_CONFIG_MODBUS_PERMISSION`是否启用Modbus映射权限校验
## 7. 硬件适配
菜单组件的硬件适配层位于`port/menu_port.h``port/menu_port.c`文件中,用户需要实现以下接口:
```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 基本使用
```c
#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 批量注册菜单节点
```c
// 定义菜单节点配置
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 参数管理
```c
// 注册参数
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 多语言支持
```c
// 注册语言字符串
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映射
```c
// 注册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语言的嵌入式系统