优化整定一版

This commit is contained in:
冯佳
2025-12-18 23:56:36 +08:00
parent e5eaf2172f
commit e36b4e0e27
16 changed files with 2619 additions and 504 deletions

View File

@ -1,139 +1,288 @@
/**
* @file menu_port.c
* @brief 菜单组件硬件端口层示例实现(用户需要根据实际硬件修改
* @note 工业级嵌入式菜单组件 - 硬件端口层示例
* @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
* @brief 默认硬件打印接口实现使用标准C库printf
* @param fmt 格式化字符串
* @param args 可变参数列表
* @note 实际项目中用户需要将此接口重定向到硬件的串口、LCD等输出设备
*/
void menu_port_printf(const char* fmt, va_list args)
static void default_printf(const char* fmt, va_list args)
{
// 示例使用标准C库的vprintf函数
// 实际项目中,这里应该调用硬件相关的打印函数,如串口打印
vprintf(fmt, args);
}
/**
* @brief 获取系统滴答时间示例实现使用标准C库time函数
* @brief 默认获取系统滴答时间实现使用标准C库time函数
* @return 当前系统滴答时间ms
* @note 实际项目中,用户需要将此接口实现为硬件定时器的计数值
*/
uint32_t menu_port_get_tick(void)
static uint32_t default_get_tick(void)
{
// 示例使用标准C库的time函数仅用于演示精度低
// 实际项目中这里应该返回硬件定时器的计数值如SysTick
return (uint32_t)time(NULL) * 1000;
}
/**
* @brief 硬件延迟函数示例实现使用标准C库sleep函数
* @brief 默认硬件延迟函数实现使用标准C库sleep函数
* @param ms 延迟时间ms
* @note 实际项目中,用户需要将此接口实现为硬件定时器的延迟
*/
void menu_port_delay_ms(uint32_t ms)
static void default_delay_ms(uint32_t ms)
{
// 示例使用标准C库的sleep函数仅用于演示精度低
// 实际项目中,这里应该使用硬件定时器实现精确延迟
sleep(ms / 1000);
usleep((ms % 1000) * 1000);
}
/**
* @brief 菜单显示接口示例实现使用标准C库printf
* @brief 默认菜单显示接口实现使用标准C库printf
* @param menu_name 菜单名称字符串
* @param menu_id 菜单ID
* @note 实际项目中用户需要将此接口实现为在LCD、OLED等显示设备上的显示
*/
void menu_port_display(const char* menu_name, uint16_t menu_id)
static void default_display(const char* menu_name, uint16_t menu_id)
{
// 示例使用标准C库的printf函数在控制台显示
// 实际项目中这里应该调用硬件显示函数将菜单显示在LCD等设备上
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 按键扫描接口示例实现(使用标准C库getchar函数
* @return 当前按键事件MenuEventType类型
* @note 实际项目中,用户需要将此接口实现为硬件按键的扫描
* @brief 默认按键扫描接口实现(无按键返回
* @return 当前按键事件
*/
/*
MenuEventType menu_port_key_scan(void)
static MenuEventType default_key_scan(void)
{
// 示例使用标准C库的getchar函数获取键盘输入仅用于演示
// 实际项目中,这里应该扫描硬件按键的状态
if (kbhit())
{
char key = getchar();
switch (key)
{
case 'w':
case 'W':
return MENU_EVENT_KEY_UP;
case 's':
case 'S':
return MENU_EVENT_KEY_DOWN;
case '\r':
case '\n':
return MENU_EVENT_KEY_ENTER;
case 'b':
case 'B':
return MENU_EVENT_KEY_BACK;
default:
break;
}
}
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硬件发送数据接口示例实现
* @brief 默认Modbus硬件发送数据接口实现(模拟成功)
* @param reg_type 寄存器类型
* @param reg_addr 寄存器地址
* @param reg_buf 数据缓冲区
* @param buf_len 数据长度
* @return 错误码
* @note 用户需要根据实际硬件如RS485、TCP实现此接口
*/
MenuErrCode menu_port_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len)
static MenuErrCode default_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len)
{
// 示例通过RS485发送Modbus写指令如写保持寄存器0x000040001
// 实际需根据Modbus协议实现帧组装、校验、发送
(void)reg_type;
(void)reg_addr;
(void)reg_buf;
(void)buf_len;
return MENU_OK; // 模拟成功,用户需替换为实际逻辑
return MENU_OK;
}
/**
* @brief Modbus硬件接收数据接口示例实现
* @brief 默认Modbus硬件接收数据接口实现(模拟成功)
* @param reg_type 寄存器类型
* @param reg_addr 寄存器地址
* @param reg_buf 数据缓冲区
* @param buf_len 数据长度
* @return 错误码
* @note 用户需要根据实际硬件如RS485、TCP实现此接口
*/
MenuErrCode menu_port_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len)
static MenuErrCode default_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len)
{
// 示例通过RS485接收Modbus读指令的响应数据
(void)reg_type;
(void)reg_addr;
(void)reg_buf;
(void)buf_len;
return MENU_OK; // 模拟成功,用户需替换为实际逻辑
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