Files
433_STM32/Core/Src/uart3_passthrough.c
zhongxuanzhen 0eea5c1424 3.27_433:实验并验证485发送数据透传至RF433模块,并在外部设备成功接收
- 新增协议识别器状态机,实现指令与透传数据的自动识别
2026-03-27 19:58:20 +08:00

269 lines
7.8 KiB
C
Raw Permalink 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 uart3_passthrough.c
* @brief UART3透传引擎模块实现
* @author Application Layer
* @version 1.0
******************************************************************************
* @attention
* 设计依据UART3智能数据路由与透传功能开发计划 第3.2节
*
* 功能说明:
* 本模块实现透传数据缓冲与发送功能将UART3接收的透传数据转发至UART1
*
* 工作流程严格按文档3.2.3节伪代码实现):
* 1. 检查是否有待发送数据
* 2. 检查UART1是否可发送
* 3. 获取当前处理节点
* 4. 发送一个字节
* 5. 更新队列状态和统计
*
* 发送机制:
* - 单字节每次发送由UART1 TX完成中断驱动连续发送
* - 使用独立环形缓冲区,避免与指令解析争用
******************************************************************************
*/
#include "uart3_passthrough.h"
#include "uart3_smart_router_config.h"
#include "multi_uart_router.h"
#include "uart2_print.h"
#include <string.h>
/*==============================================================================
* 调试宏定义
*============================================================================*/
#if DEBUG_PASSTHROUGH_ENGINE
#define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[PTX] " fmt "\r\n", ##__VA_ARGS__)
#else
#define DEBUG_LOG(fmt, ...)
#endif
/*==============================================================================
* 全局变量定义
* 设计依据文档第3.2.2节
*============================================================================*/
/**
* @brief 透传引擎全局上下文
* @note 保存透传引擎全部状态信息
*/
passthrough_context_t g_passthrough_ctx;
/*==============================================================================
* 公共函数实现
* 设计依据文档第3.2.1节模块接口设计
*============================================================================*/
/**
* @brief 透传引擎初始化
* @note 初始化透传队列和统计信息
*/
void Passthrough_Init(void)
{
memset(&g_passthrough_ctx, 0, sizeof(g_passthrough_ctx));
for (uint8_t i = 0; i < PASSTHROUGH_MAX_NODES; i++) {
g_passthrough_ctx.queue.nodes[i].valid = false;
g_passthrough_ctx.queue.nodes[i].length = 0;
g_passthrough_ctx.queue.nodes[i].offset = 0;
}
g_passthrough_ctx.queue.write_index = 0;
g_passthrough_ctx.queue.read_index = 0;
g_passthrough_ctx.queue.pending_count = 0;
g_passthrough_ctx.stats.total_bytes_sent = 0;
g_passthrough_ctx.stats.total_packets = 0;
g_passthrough_ctx.stats.overflow_count = 0;
g_passthrough_ctx.stats.busy_count = 0;
g_passthrough_ctx.initialized = true;
DEBUG_LOG("Passthrough engine initialized, buffer size: %d bytes", PASSTHROUGH_TOTAL_BUFFER);
}
/**
* @brief 压入单字节到透传缓冲区
* @note 将单个字节添加到透传发送队列
* @param byte: 待发送字节
* @retval bool: true=成功false=缓冲区满
*/
bool Passthrough_PushByte(uint8_t byte)
{
passthrough_context_t *ctx = &g_passthrough_ctx;
if (!ctx->initialized) {
return false;
}
uint8_t next_index = (ctx->queue.write_index + 1) % PASSTHROUGH_MAX_NODES;
if (next_index == ctx->queue.read_index && ctx->queue.pending_count > 0) {
ctx->stats.overflow_count++;
DEBUG_LOG("Buffer full, overflow count: %d", ctx->stats.overflow_count);
return false;
}
passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.write_index];
if (!node->valid || node->length >= PASSTHROUGH_NODE_SIZE) {
if (node->valid) {
ctx->queue.write_index = next_index;
node = &ctx->queue.nodes[ctx->queue.write_index];
}
node->length = 0;
node->offset = 0;
node->valid = true;
}
node->data[node->length++] = byte;
ctx->queue.pending_count++;
return true;
}
/**
* @brief 压入数据块到透传缓冲区
* @note 将数据块添加到透传发送队列
* @param data: 数据缓冲区指针
* @param length: 数据长度
* @retval uint16_t: 实际写入的字节数
*/
uint16_t Passthrough_PushBuffer(const uint8_t *data, uint16_t length)
{
if (data == NULL || length == 0) {
return 0;
}
passthrough_context_t *ctx = &g_passthrough_ctx;
uint16_t written = 0;
for (uint16_t i = 0; i < length; i++) {
uint8_t next_index = (ctx->queue.write_index + 1) % PASSTHROUGH_MAX_NODES;
if (next_index == ctx->queue.read_index && ctx->queue.pending_count > 0) {
ctx->stats.overflow_count++;
DEBUG_LOG("Buffer overflow at byte %d/%d", i, length);
break;
}
passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.write_index];
if (!node->valid || node->length >= PASSTHROUGH_NODE_SIZE) {
if (node->valid) {
ctx->queue.write_index = next_index;
node = &ctx->queue.nodes[ctx->queue.write_index];
}
node->length = 0;
node->offset = 0;
node->valid = true;
}
node->data[node->length++] = data[i];
ctx->queue.pending_count++;
written++;
}
if (written > 0) {
ctx->stats.total_packets++;
DEBUG_LOG("Pushed %d bytes to buffer, pending: %d", written, ctx->queue.pending_count);
}
return written;
}
/**
* @brief 透传引擎任务
* @note 在主循环中周期性调用,每次尝试发送一个字节
* 配合UART1 TX完成中断实现连续发送
*/
void Passthrough_Task(void)
{
passthrough_context_t *ctx = &g_passthrough_ctx;
if (!ctx->initialized) {
return;
}
if (ctx->queue.pending_count == 0) {
return;
}
if (!Passthrough_CanSend()) {
ctx->stats.busy_count++;
return;
}
passthrough_node_t *node = &ctx->queue.nodes[ctx->queue.read_index];
if (!node->valid || node->offset >= node->length) {
if (node->valid) {
node->valid = false;
}
ctx->queue.read_index = (ctx->queue.read_index + 1) % PASSTHROUGH_MAX_NODES;
return;
}
uint8_t byte = node->data[node->offset++];
MultiUART_Send(PORT_UART1, &byte, 1);
ctx->queue.pending_count--;
ctx->stats.total_bytes_sent++;
DEBUG_LOG("Sent byte 0x%02X, pending: %d", byte, ctx->queue.pending_count);
}
/**
* @brief UART1发送完成回调
* @note 应在HAL_UART_TxCpltCallback中调用触发下一次发送
*/
void Passthrough_OnTxComplete(void)
{
Passthrough_Task();
}
/**
* @brief 检查UART1是否可发送
* @note 检查UART1发送缓冲区是否有空间
* @retval bool: true=可发送false=忙
*/
bool Passthrough_CanSend(void)
{
return (MultiUART_GetTxAvailable(PORT_UART1) > 0) &&
(g_passthrough_ctx.queue.pending_count > 0);
}
/**
* @brief 获取透传统计信息
* @note 获取透传引擎的运行统计
* @param stats: 统计结构指针
*/
void Passthrough_GetStats(passthrough_stats_t *stats)
{
if (stats != NULL) {
memcpy(stats, &g_passthrough_ctx.stats, sizeof(passthrough_stats_t));
}
}
/**
* @brief 重置统计信息
* @note 清零所有统计计数器
*/
void Passthrough_ResetStats(void)
{
passthrough_context_t *ctx = &g_passthrough_ctx;
ctx->stats.total_bytes_sent = 0;
ctx->stats.total_packets = 0;
ctx->stats.overflow_count = 0;
ctx->stats.busy_count = 0;
DEBUG_LOG("Stats reset");
}
/**
* @brief 获取待发送字节数
* @note 获取队列中等待发送的字节总数
* @retval uint16_t: 待发送字节数
*/
uint16_t Passthrough_GetPendingCount(void)
{
return g_passthrough_ctx.queue.pending_count;
}