/** ********************************************************************************************************************** * @file menu_port.c * @brief 菜单组件硬件端口层实现 * @author menu_component * @date 2025-12-19 ********************************************************************************************************************** */ /* Includes ----------------------------------------------------------------------------------------------------------*/ #include "menu_port.h" #include #include /* 全局变量 ---------------------------------------------------------------------------------------------------------*/ static const MenuPortDriver* sg_menu_port_driver = NULL; /* 默认硬件驱动实现 -------------------------------------------------------------------------------------------------*/ /** * @brief 默认打印函数 * @param fmt 格式化字符串 * @param args 可变参数列表 */ static void menu_port_default_printf(const char* fmt, va_list args) { // 默认不实现打印功能 (void)fmt; (void)args; } /** * @brief 默认获取系统时间函数 * @return 系统时间(ms) */ static uint32_t menu_port_default_get_tick(void) { // 默认返回0,用户需要根据实际硬件实现 return 0; } /** * @brief 默认延迟函数 * @param ms 延迟时间(ms) */ static void menu_port_default_delay_ms(uint32_t ms) { // 默认实现简单的延迟 for (uint32_t i = 0; i < ms * 1000; i++) { __asm__ volatile ("nop"); } } /** * @brief 默认显示函数 * @param menu_name 菜单名称 * @param menu_id 菜单ID */ static void menu_port_default_display(const char* menu_name, uint16_t menu_id) { // 默认不实现显示功能 (void)menu_name; (void)menu_id; } /** * @brief 默认按键扫描函数 * @return 按键事件类型 */ static MenuEventType menu_port_default_key_scan(void) { // 默认返回无事件 return MENU_EVENT_NONE; } /** * @brief 默认中断管理函数 * @param enable 是否启用中断 */ static void menu_port_default_irq_ctrl(bool enable) { // 默认不实现中断管理 (void)enable; } /** * @brief 默认错误处理函数 * @param err_code 错误码 */ static void menu_port_default_error_handler(MenuErrCode err_code) { // 默认不实现错误处理 (void)err_code; } /** * @brief 默认Modbus发送函数 * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 寄存器数据 * @param buf_len 数据长度 * @return 错误码 */ static MenuErrCode menu_port_default_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len) { // 默认不实现Modbus发送 (void)reg_type; (void)reg_addr; (void)reg_buf; (void)buf_len; return MENU_ERR_OPERATION_FAILED; } /** * @brief 默认Modbus接收函数 * @param reg_type 寄存器类型 * @param reg_addr 寄存器地址 * @param reg_buf 寄存器数据 * @param buf_len 数据长度 * @return 错误码 */ static MenuErrCode menu_port_default_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len) { // 默认不实现Modbus接收 (void)reg_type; (void)reg_addr; (void)reg_buf; (void)buf_len; return MENU_ERR_OPERATION_FAILED; } /** * @brief 默认持久化保存函数 * @param data 要保存的数据 * @param size 数据大小 * @return 错误码 */ static MenuErrCode menu_port_default_persistence_save(const uint8_t* data, uint16_t size) { // 默认不实现持久化保存功能 (void)data; (void)size; return MENU_ERR_OPERATION_FAILED; } /** * @brief 默认持久化恢复函数 * @param data 恢复数据缓冲区 * @param size 数据大小 * @return 错误码 */ static MenuErrCode menu_port_default_persistence_restore(uint8_t* data, uint16_t* size) { // 默认不实现持久化恢复功能 (void)data; (void)size; return MENU_ERR_OPERATION_FAILED; } /** * @brief 默认硬件驱动 */ static const MenuPortDriver sg_default_driver = { .printf = menu_port_default_printf, .get_tick = menu_port_default_get_tick, .delay_ms = menu_port_default_delay_ms, .display = menu_port_default_display, .key_scan = menu_port_default_key_scan, .irq_ctrl = menu_port_default_irq_ctrl, .error_handler = menu_port_default_error_handler, .modbus_send = menu_port_default_modbus_send, .modbus_receive = menu_port_default_modbus_receive, .persistence_save = menu_port_default_persistence_save, .persistence_restore = menu_port_default_persistence_restore, }; /* 函数实现 ---------------------------------------------------------------------------------------------------------*/ /** * @brief 初始化硬件端口层 * @param driver 硬件驱动结构体指针 * @return 错误码 */ MenuErrCode menu_port_init(const MenuPortDriver* driver) { if (driver != NULL) { sg_menu_port_driver = driver; } else { sg_menu_port_driver = &sg_default_driver; } return MENU_ERR_OK; } /** * @brief 反初始化硬件端口层 * @return 错误码 */ MenuErrCode menu_port_deinit(void) { sg_menu_port_driver = NULL; return MENU_ERR_OK; } /** * @brief 获取当前系统时间(ms) * @return 系统时间(ms) */ uint32_t menu_port_get_tick(void) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->get_tick != NULL) { return sg_menu_port_driver->get_tick(); } return menu_port_default_get_tick(); } /** * @brief 硬件延迟函数 * @param ms 延迟时间(ms) */ void menu_port_delay_ms(uint32_t ms) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->delay_ms != NULL) { sg_menu_port_driver->delay_ms(ms); } else { menu_port_default_delay_ms(ms); } } /** * @brief 打印函数 * @param fmt 格式化字符串 * @param ... 可变参数 */ void menu_port_printf(const char* fmt, ...) { va_list args; va_start(args, fmt); if (sg_menu_port_driver != NULL && sg_menu_port_driver->printf != NULL) { sg_menu_port_driver->printf(fmt, args); } else { menu_port_default_printf(fmt, args); } va_end(args); } /** * @brief 菜单显示函数 * @param menu_name 菜单名称 * @param menu_id 菜单ID */ void menu_port_display(const char* menu_name, uint16_t menu_id) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->display != NULL) { sg_menu_port_driver->display(menu_name, menu_id); } else { menu_port_default_display(menu_name, menu_id); } } /** * @brief 按键扫描函数 * @return 按键事件类型 */ MenuEventType menu_port_key_scan(void) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->key_scan != NULL) { return sg_menu_port_driver->key_scan(); } return menu_port_default_key_scan(); } /** * @brief 中断管理函数 * @param enable 是否启用中断 */ void menu_port_irq_ctrl(bool enable) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->irq_ctrl != NULL) { sg_menu_port_driver->irq_ctrl(enable); } else { menu_port_default_irq_ctrl(enable); } } /** * @brief 错误处理函数 * @param err_code 错误码 */ void menu_port_error_handler(MenuErrCode err_code) { if (sg_menu_port_driver != NULL && sg_menu_port_driver->error_handler != NULL) { sg_menu_port_driver->error_handler(err_code); } else { menu_port_default_error_handler(err_code); } } /** * @brief 断言失败处理函数 * @param expr 断言表达式 * @param file 文件名 * @param line 行号 */ void menu_assert_failed(const char* expr, const char* file, uint32_t line) { // 打印断言失败信息 char buf[128] = {0}; snprintf(buf, sizeof(buf), "Assertion failed: %s, file %s, line %lu\n", expr, file, (unsigned long)line); // 直接使用printf输出,因为menu_port_printf需要va_list参数 printf("%s", buf); // 进入死循环 while (1) { // 可以添加其他处理逻辑,如复位系统等 } }