/** * @file menu_port.c * @brief 菜单组件硬件端口层实现(模块化设计,支持运行时配置) * @note 工业级嵌入式菜单组件 - 硬件端口层 * @attention 用户需要根据自己的硬件平台修改此文件 */ #include "menu_port.h" #include "menu.h" #include #include #include #include /************************** 静态全局变量 **************************/ static const MenuPortDriver* g_current_driver = NULL; /************************** 默认驱动实现 **************************/ /** * @brief 默认硬件打印接口实现(使用标准C库printf) * @param fmt 格式化字符串 * @param args 可变参数列表 */ static void default_printf(const char* fmt, va_list args) { vprintf(fmt, args); } /** * @brief 默认获取系统滴答时间实现(使用标准C库time函数) * @return 当前系统滴答时间(ms) */ static uint32_t default_get_tick(void) { return (uint32_t)time(NULL) * 1000; } /** * @brief 默认硬件延迟函数实现(使用标准C库sleep函数) * @param ms 延迟时间(ms) */ static void default_delay_ms(uint32_t ms) { sleep(ms / 1000); usleep((ms % 1000) * 1000); } /** * @brief 默认菜单显示接口实现(使用标准C库printf) * @param menu_name 菜单名称字符串 * @param menu_id 菜单ID */ static void default_display(const char* menu_name, uint16_t menu_id) { printf("\r\nCurrent Menu: %s (ID: %d)\r\n", menu_name, menu_id); printf("Use UP/DOWN keys to navigate, ENTER to select, BACK to return\r\n"); } /** * @brief 默认按键扫描接口实现(无按键返回) * @return 当前按键事件 */ static MenuEventType default_key_scan(void) { return MENU_EVENT_NONE; } /** * @brief 默认中断管理接口实现(空操作) * @param enable 中断使能标志 */ static void default_irq_ctrl(bool enable) { (void)enable; // 默认实现为空,用户需根据硬件平台实现 } /** * @brief 默认错误处理接口实现(打印错误信息) * @param err_code 错误码 */ static void default_error_handler(MenuErrCode err_code) { fprintf(stderr, "[MENU HW ERROR] %d\r\n", err_code); } #if MENU_CONFIG_ENABLE_MODBUS_MAP /** * @brief 默认Modbus硬件发送数据接口实现(模拟成功) * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 数据缓冲区 * @param buf_len 数据长度 * @return 错误码 */ static MenuErrCode default_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len) { (void)reg_type; (void)reg_addr; (void)reg_buf; (void)buf_len; return MENU_OK; } /** * @brief 默认Modbus硬件接收数据接口实现(模拟成功) * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 数据缓冲区 * @param buf_len 数据长度 * @return 错误码 */ static MenuErrCode default_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len) { (void)reg_type; (void)reg_addr; (void)reg_buf; (void)buf_len; return MENU_OK; } #endif // MENU_CONFIG_ENABLE_MODBUS_MAP /** * @brief 默认硬件驱动结构体(提供基本实现,减少用户工作量) */ const MenuPortDriver g_menu_default_driver = { .printf = default_printf, .get_tick = default_get_tick, .delay_ms = default_delay_ms, .display = default_display, .key_scan = default_key_scan, .irq_ctrl = default_irq_ctrl, .error_handler = default_error_handler, #if MENU_CONFIG_ENABLE_MODBUS_MAP .modbus_send = default_modbus_send, .modbus_receive = default_modbus_receive, #endif // MENU_CONFIG_ENABLE_MODBUS_MAP }; /************************** 端口管理函数 **************************/ /** * @brief 硬件端口初始化接口 * @param driver 硬件驱动结构体指针 * @return 错误码 */ MenuErrCode menu_port_init(const MenuPortDriver* driver) { if (driver == NULL) { // 使用默认驱动 g_current_driver = &g_menu_default_driver; } else { // 使用用户提供的驱动,替换为默认驱动中未实现的部分 g_current_driver = driver; } return MENU_OK; } /** * @brief 硬件端口反初始化接口 * @return 错误码 */ MenuErrCode menu_port_deinit(void) { g_current_driver = NULL; return MENU_OK; } /** * @brief 获取当前硬件驱动 * @return 当前硬件驱动结构体指针 */ const MenuPortDriver* menu_port_get_driver(void) { if (g_current_driver == NULL) { // 确保始终有驱动可用 return &g_menu_default_driver; } return g_current_driver; } /************************** 兼容旧接口的实现 **************************/ /** * @brief 硬件打印接口(兼容旧接口) * @param fmt 格式化字符串 * @param args 可变参数列表 */ void menu_port_printf(const char* fmt, va_list args) { const MenuPortDriver* driver = menu_port_get_driver(); if (driver->printf != NULL) { driver->printf(fmt, args); } } /** * @brief 获取系统滴答时间(兼容旧接口) * @return 当前系统滴答时间(ms) */ uint32_t menu_port_get_tick(void) { const MenuPortDriver* driver = menu_port_get_driver(); if (driver->get_tick != NULL) { return driver->get_tick(); } return 0; } /** * @brief 硬件延迟函数(兼容旧接口) * @param ms 延迟时间(ms) */ void menu_port_delay_ms(uint32_t ms) { const MenuPortDriver* driver = menu_port_get_driver(); if (driver->delay_ms != NULL) { driver->delay_ms(ms); } } /** * @brief 菜单显示接口(兼容旧接口) * @param menu_name 菜单名称字符串 * @param menu_id 菜单ID */ void menu_port_display(const char* menu_name, uint16_t menu_id) { const MenuPortDriver* driver = menu_port_get_driver(); if (driver->display != NULL) { driver->display(menu_name, menu_id); } } #if MENU_CONFIG_ENABLE_MODBUS_MAP /** * @brief Modbus硬件发送数据接口(兼容旧接口) * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 数据缓冲区 * @param buf_len 数据长度 * @return 错误码 */ MenuErrCode menu_port_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len) { const MenuPortDriver* driver = menu_port_get_driver(); #if MENU_CONFIG_ENABLE_MODBUS_MAP if (driver->modbus_send != NULL) { return driver->modbus_send(reg_type, reg_addr, reg_buf, buf_len); } #endif // MENU_CONFIG_ENABLE_MODBUS_MAP return MENU_OK; } /** * @brief Modbus硬件接收数据接口(兼容旧接口) * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 数据缓冲区 * @param buf_len 数据长度 * @return 错误码 */ MenuErrCode menu_port_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len) { const MenuPortDriver* driver = menu_port_get_driver(); #if MENU_CONFIG_ENABLE_MODBUS_MAP if (driver->modbus_receive != NULL) { return driver->modbus_receive(reg_type, reg_addr, reg_buf, buf_len); } #endif // MENU_CONFIG_ENABLE_MODBUS_MAP return MENU_OK; } #endif // MENU_CONFIG_ENABLE_MODBUS_MAP