Files
menu/api/menu.h
2025-12-18 22:24:25 +08:00

243 lines
8.5 KiB
C
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.

/**
* @file menu.h
* @brief 菜单组件对外暴露的核心接口(用户唯一需要包含的头文件)
* @note 工业级嵌入式菜单组件 - 对外API层
*/
#ifndef MENU_H
#define MENU_H
#include "menu_config.h"
#include <stdint.h>
#include <stdbool.h>
/************************** 全局类型导出 **************************/
/**
* @brief 菜单错误码(工业级错误处理:明确所有可能的错误类型)
*/
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 ///< 硬件端口层错误
} MenuErrCode;
/**
* @brief 菜单事件类型(事件驱动核心:解耦按键与菜单逻辑)
*/
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;
/**
* @brief 菜单节点ID类型统一标识
*/
typedef uint16_t MenuNodeId;
/**
* @brief 菜单回调函数类型(菜单选中/退出时的执行逻辑)
* @param node_id 触发回调的菜单节点ID
* @return 错误码
*/
typedef MenuErrCode (*MenuCallback)(MenuNodeId node_id);
/************************** 核心接口声明 **************************/
/**
* @brief 菜单组件初始化(必须首先调用)
* @return 错误码
*/
MenuErrCode menu_init(void);
/**
* @brief 菜单主循环(需在用户主循环中调用,处理事件和刷新显示)
*/
void menu_main_loop(void);
/**
* @brief 发送事件到菜单事件队列(如按键事件、自定义事件)
* @param type 事件类型
* @param param 事件附加参数(可选,如按键长按时间)
* @return 错误码
*/
MenuErrCode menu_post_event(MenuEventType type, uint32_t param);
/**
* @brief 注册菜单节点(构建菜单树)
* @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(MenuNodeId parent_id, MenuNodeId node_id, const char* name_str, MenuCallback enter_cb, MenuCallback exit_cb);
/**
* @brief 获取当前选中的菜单节点ID
* @param node_id 输出参数当前节点ID
* @return 错误码
*/
MenuErrCode menu_get_current_node(MenuNodeId* node_id);
/************************** 功能扩展接口声明(可裁剪) **************************/
#if MENU_CONFIG_ENABLE_PARAM
/**
* @brief 参数类型枚举
*/
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;
/**
* @brief 注册参数到菜单节点(参数管理功能)
* @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(MenuNodeId node_id, uint16_t param_id, MenuParamType type, float min_val, float max_val, float default_val, float scale);
/**
* @brief 设置参数值
* @param param_id 参数ID
* @param value 新值(浮点型,内部自动转换)
* @return 错误码
*/
MenuErrCode menu_param_set_value(uint16_t param_id, float value);
/**
* @brief 获取参数值
* @param param_id 参数ID
* @param value 输出参数,当前值(浮点型)
* @return 错误码
*/
MenuErrCode menu_param_get_value(uint16_t param_id, float* value);
/**
* @brief 获取参数类型
* @param param_id 参数ID
* @param type 输出参数,参数类型
* @return 错误码
*/
MenuErrCode menu_param_get_type(uint16_t param_id, MenuParamType* type);
#endif // MENU_CONFIG_ENABLE_PARAM
#if MENU_CONFIG_ENABLE_LANG
/**
* @brief 设置当前语言
* @param lang_id 语言ID如0-中文1-英文)
* @return 错误码
*/
MenuErrCode menu_lang_set_current(uint8_t lang_id);
/**
* @brief 获取当前语言
* @param lang_id 输出参数当前语言ID
* @return 错误码
*/
MenuErrCode menu_lang_get_current(uint8_t* lang_id);
#endif // MENU_CONFIG_ENABLE_LANG
/************************** Modbus映射功能启用时有效 **************************/
#if MENU_CONFIG_ENABLE_MODBUS_MAP
/**
* @brief Modbus寄存器类型符合Modbus协议标准
*/
typedef enum {
MODBUS_REG_TYPE_COIL = 0, ///< 线圈1位地址范围00001-09999
MODBUS_REG_TYPE_DISCRETE_INPUT, ///< 离散输入1位地址范围10001-19999
MODBUS_REG_TYPE_HOLDING_REG, ///< 保持寄存器16位地址范围40001-49999
MODBUS_REG_TYPE_INPUT_REG, ///< 输入寄存器16位地址范围30001-39999
} ModbusRegType;
/**
* @brief Modbus寄存器读写权限
*/
typedef enum {
MODBUS_PERM_READ_ONLY = 0, ///< 只读(如离散输入、输入寄存器)
MODBUS_PERM_WRITE_ONLY, ///< 只写(如线圈)
MODBUS_PERM_READ_WRITE, ///< 读写(如保持寄存器)
} ModbusPerm;
/**
* @brief Modbus映射结构体对外只读内部初始化
*/
typedef struct {
uint16_t param_id; ///< 关联的参数ID
ModbusRegType reg_type; ///< 寄存器类型
uint16_t reg_addr; ///< 寄存器起始地址协议地址如40001
uint8_t reg_count; ///< 占用寄存器数量如32位浮点占2个16位寄存器
ModbusPerm perm; ///< 读写权限
uint8_t byte_order; ///< 字节序0-小端1-大端2-Modbus标准
} ModbusMap;
/**
* @brief 注册参数与Modbus寄存器的映射关系
* @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(uint16_t param_id, ModbusRegType reg_type, uint16_t reg_addr, uint8_t reg_count, ModbusPerm perm, uint8_t byte_order);
/**
* @brief 根据参数ID查询Modbus映射关系
* @param param_id 参数ID
* @param map 输出参数,映射关系结构体
* @return 错误码
*/
MenuErrCode menu_modbus_map_query_by_param(uint16_t param_id, ModbusMap* map);
/**
* @brief 根据寄存器地址和类型查询Modbus映射关系
* @param reg_type 寄存器类型
* @param reg_addr 寄存器地址
* @param map 输出参数,映射关系结构体
* @return 错误码
*/
MenuErrCode menu_modbus_map_query_by_reg(ModbusRegType reg_type, uint16_t reg_addr, ModbusMap* map);
/**
* @brief 将参数值写入对应的Modbus寄存器双向转换参数值→寄存器数据
* @param param_id 参数ID
* @param reg_buf 输出参数寄存器数据缓冲区需足够大如32位占2个16位寄存器
* @param buf_len 缓冲区长度(输入),实际写入长度(输出)
* @return 错误码
*/
MenuErrCode menu_modbus_map_param_to_reg(uint16_t param_id, uint8_t* reg_buf, uint8_t* buf_len);
/**
* @brief 将Modbus寄存器数据读取到参数值双向转换寄存器数据→参数值
* @param param_id 参数ID
* @param reg_buf 输入参数,寄存器数据缓冲区
* @param buf_len 缓冲区长度
* @return 错误码
*/
MenuErrCode menu_modbus_map_reg_to_param(uint16_t param_id, const uint8_t* reg_buf, uint8_t buf_len);
#endif // MENU_CONFIG_ENABLE_MODBUS_MAP
#endif // MENU_H