Files
menu/port/menu_port.c
2025-12-19 17:01:27 +08:00

320 lines
8.0 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 菜单组件硬件端口层实现
* @author menu_component
* @date 2025-12-19
**********************************************************************************************************************
*/
/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "menu_port.h"
#include <stdarg.h>
#include <stdio.h>
/* 全局变量 ---------------------------------------------------------------------------------------------------------*/
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) {
// 可以添加其他处理逻辑,如复位系统等
}
}