本次重构完成了 433MHz 全链路协议统一:实现了 AA TYPE LEN ID PAYLOAD SUM 统一帧格式;引入了基于 AUX 的 LBT 避让与 TX 优先调度,确保高频发送稳定;完成了端口语义化重命名;并成功集成了 IO 监控、RS485 及 W5500 以太网 的标准化打包转发,实现了多源数据的高效、稳定透传。

This commit is contained in:
edisondeng
2026-05-08 15:25:19 +08:00
parent de67b86952
commit 878379f101
11 changed files with 793 additions and 121 deletions

View File

@ -16,14 +16,15 @@
* 4. 响应路由表
*
* 端口映射:
* - PORT_UART1: 连接RF433无线模块(用于无线数据收发)
* - PORT_UART2: 调试串口(用于日志和调试输出)
* - PORT_UART3: 预留扩展端口
* - PORT_433: 连接RF433无线模块(用于无线数据收发)
* - PORT_DEBUG: 调试串口(用于日志和调试输出)
* - PORT_RS485: 预留扩展端口
******************************************************************************
*/
#include "multi_uart_router.h"
#include "uart2_print.h"
#include "main.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
@ -57,9 +58,9 @@ static uart_port_context_t g_port_ctx[PORT_COUNT];
* 使用常量初始化,在编译时确定,无运行时开销
*/
static UART_HandleTypeDef *const g_port_uart_map[PORT_COUNT] = {
[PORT_UART1] = &huart1, /**< RF433无线模块 */
[PORT_UART2] = &huart2, /**< 调试串口 */
[PORT_UART3] = &huart3, /**< 预留扩展 */
[PORT_433] = &huart1, /**< RF433无线模块 */
[PORT_DEBUG] = &huart2, /**< 调试串口 */
[PORT_RS485] = &huart3, /**< 预留扩展 */
};
/**
@ -67,9 +68,9 @@ static UART_HandleTypeDef *const g_port_uart_map[PORT_COUNT] = {
* @note 用于调试日志输出,快速获取端口的可读名称
*/
static const char *const g_port_name_map[PORT_COUNT] = {
[PORT_UART1] = "UART1", /**< RF433无线模块 */
[PORT_UART2] = "UART2", /**< 调试串口 */
[PORT_UART3] = "UART3", /**< 预留扩展 */
[PORT_433] = "UART1", /**< RF433无线模块 */
[PORT_DEBUG] = "UART2", /**< 调试串口 */
[PORT_RS485] = "UART3", /**< 预留扩展 */
};
/*==============================================================================
@ -234,6 +235,15 @@ static void tx_kickoff(port_id_t port_id)
__disable_irq();
if (!ring->is_sending && ring->count > 0) {
/* --- 核心修复:针对 RF433 (UART1) 执行包级 LBT 检查 --- */
if (port_id == PORT_433) {
// 如果 AUX 为低电平,说明信道忙(接收中或正在发送前一包),暂缓起步
if (HAL_GPIO_ReadPin(AUX_GPIO_Port, AUX_Pin) == GPIO_PIN_RESET) {
__enable_irq();
return;
}
}
/* 取出下一个待发送字节 */
byte = ring->buffer[ring->tail];
ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE;
@ -344,7 +354,7 @@ void MultiUART_FeedByte(port_id_t port_id, uint8_t byte)
* 接收处理由中断完成(MultiUART_FeedByte),此函数仅处理发送
*
* 端口跳过说明:
* - 跳过PORT_UART2(调试串口)由UART2_Print模块独立处理
* - 跳过PORT_DEBUG(调试串口)由UART2_Print模块独立处理
*
* 调用时机:
* 建议在主循环中周期性调用(如10ms定时)
@ -360,7 +370,7 @@ void MultiUART_Task(void)
}
/* 跳过调试串口(UART2) */
if (i == PORT_UART2) {
if (i == PORT_DEBUG) {
continue;
}
@ -379,7 +389,7 @@ void MultiUART_Task(void)
* @return 无
*
* 特殊处理:
* - PORT_UART2直接调用UART2_Print_Send由调试模块处理
* - PORT_DEBUG直接调用UART2_Print_Send由调试模块处理
* - 其他端口使用本模块的环形缓冲区机制
*
* 发送流程:
@ -400,7 +410,7 @@ void MultiUART_Send(port_id_t port_id, const uint8_t *data, uint16_t len)
* 调试串口(UART2)特殊处理
* 调试打印不走环形缓冲区,直接发送
*----------------------------------------------------------*/
if (port_id == PORT_UART2) {
if (port_id == PORT_DEBUG) {
UART2_Print_Send(data, len);
return;
}
@ -487,7 +497,7 @@ void MultiUART_SendFmt(port_id_t port_id, const char *fmt, ...)
* @return 无
*
* 特殊处理:
* - PORT_UART2调用UART2_Print_TxCpltCallback处理
* - PORT_DEBUG调用UART2_Print_TxCpltCallback处理
*
* 发送驱动逻辑:
* 1. 清除is_sending标志
@ -504,7 +514,7 @@ void MultiUART_TxCpltCallback(port_id_t port_id)
}
/* 调试串口(UART2)特殊处理 */
if (port_id == PORT_UART2) {
if (port_id == PORT_DEBUG) {
UART2_Print_TxCpltCallback();
return;
}
@ -660,3 +670,22 @@ uint32_t MultiUART_GetOverflowCount(port_id_t port_id)
return g_port_ctx[port_id].rx_ring.overflow_count +
g_port_ctx[port_id].tx_ring.overflow_count;
}
/**
* @brief 检查指定端口是否正忙于发送
* @param port_id: 端口ID
* @return bool: true=忙碌(有待发数据或硬件发送中), false=空闲
*/
bool MultiUART_IsBusy(uint8_t port_id)
{
if (port_id >= PORT_COUNT) return false;
// 调试串口特殊处理
if (port_id == PORT_UART2) {
// UART2_Print 使用单独的标志位,这里简单兼容
return false;
}
// 直接读取状态,不屏蔽中断,追求极致性能
return (g_port_ctx[port_id].tx_ring.count > 0 || g_port_ctx[port_id].tx_ring.is_sending);
}