Files
menu/port/menu_port.c
2025-12-18 23:56:36 +08:00

288 lines
7.3 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_port.c
* @brief 菜单组件硬件端口层实现(模块化设计,支持运行时配置)
* @note 工业级嵌入式菜单组件 - 硬件端口层
* @attention 用户需要根据自己的硬件平台修改此文件
*/
#include "menu_port.h"
#include "menu.h"
#include <stdio.h>
#include <stddef.h>
#include <time.h>
#include <unistd.h>
/************************** 静态全局变量 **************************/
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