288 lines
7.3 KiB
C
288 lines
7.3 KiB
C
/**
|
||
* @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
|