3.27_433:实现并验证RF433模块接收相应指令:新增UART路由核心模块,使程序能响应RF433/RS485指令,并向UART2输出LOG(RS485由于硬件原因未验证)
This commit is contained in:
351
Core/Src/multi_uart_router.c
Normal file
351
Core/Src/multi_uart_router.c
Normal file
@ -0,0 +1,351 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file multi_uart_router.c
|
||||
* @brief 多UART统一路由核心模块实现
|
||||
* @author Application Layer
|
||||
* @version 1.0
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* 本模块实现多UART端口的统一管理
|
||||
* 设计依据:多通信接口统一指令处理系统开发计划 第3.1、3.3、3.5节及附录A
|
||||
*
|
||||
* 关键特性:
|
||||
* 1. 中断+环形缓冲区接收机制
|
||||
* 2. 非阻塞发送机制
|
||||
* 3. 端口上下文表管理
|
||||
* 4. 响应路由表
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "multi_uart_router.h"
|
||||
#include "uart2_print.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEBUG_MULTI_UART 1
|
||||
|
||||
#if DEBUG_MULTI_UART
|
||||
#define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[MUART] " fmt "\r\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_LOG(fmt, ...)
|
||||
#endif
|
||||
|
||||
static uart_port_context_t g_port_ctx[PORT_COUNT];
|
||||
|
||||
static UART_HandleTypeDef *const g_port_uart_map[PORT_COUNT] = {
|
||||
[PORT_UART1] = &huart1,
|
||||
[PORT_UART2] = &huart2,
|
||||
[PORT_UART3] = &huart3,
|
||||
};
|
||||
|
||||
static const char *const g_port_name_map[PORT_COUNT] = {
|
||||
[PORT_UART1] = "UART1",
|
||||
[PORT_UART2] = "UART2",
|
||||
[PORT_UART3] = "UART3",
|
||||
};
|
||||
|
||||
static void rx_ring_init(uart_rx_ring_t *ring)
|
||||
{
|
||||
ring->head = 0;
|
||||
ring->tail = 0;
|
||||
ring->count = 0;
|
||||
ring->overflow_count = 0;
|
||||
}
|
||||
|
||||
static void tx_ring_init(uart_tx_ring_t *ring)
|
||||
{
|
||||
ring->head = 0;
|
||||
ring->tail = 0;
|
||||
ring->count = 0;
|
||||
ring->is_sending = false;
|
||||
ring->overflow_count = 0;
|
||||
}
|
||||
|
||||
static bool rx_ring_push(uart_rx_ring_t *ring, uint8_t byte)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
__disable_irq();
|
||||
if (ring->count >= UART_RX_BUFFER_SIZE) {
|
||||
ring->overflow_count++;
|
||||
success = false;
|
||||
} else {
|
||||
ring->buffer[ring->head] = byte;
|
||||
ring->head = (ring->head + 1) % UART_RX_BUFFER_SIZE;
|
||||
ring->count++;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static uint16_t rx_ring_pop(uart_rx_ring_t *ring, uint8_t *byte)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
|
||||
__disable_irq();
|
||||
if (ring->count > 0) {
|
||||
*byte = ring->buffer[ring->tail];
|
||||
ring->tail = (ring->tail + 1) % UART_RX_BUFFER_SIZE;
|
||||
ring->count--;
|
||||
result = 1;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint16_t tx_ring_push(uart_tx_ring_t *ring, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint16_t written = 0;
|
||||
|
||||
__disable_irq();
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
if (ring->count >= UART_TX_BUFFER_SIZE) {
|
||||
ring->overflow_count++;
|
||||
break;
|
||||
}
|
||||
ring->buffer[ring->head] = data[i];
|
||||
ring->head = (ring->head + 1) % UART_TX_BUFFER_SIZE;
|
||||
ring->count++;
|
||||
written++;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static void tx_kickoff(port_id_t port_id)
|
||||
{
|
||||
uart_port_context_t *ctx = &g_port_ctx[port_id];
|
||||
uart_tx_ring_t *ring = &ctx->tx_ring;
|
||||
uint8_t byte;
|
||||
bool has_data = false;
|
||||
|
||||
__disable_irq();
|
||||
if (!ring->is_sending && ring->count > 0) {
|
||||
byte = ring->buffer[ring->tail];
|
||||
ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE;
|
||||
ring->count--;
|
||||
ring->is_sending = true;
|
||||
has_data = true;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
if (has_data) {
|
||||
HAL_UART_Transmit_IT(ctx->huart, &byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUART_Init(void)
|
||||
{
|
||||
for (port_id_t i = 0; i < PORT_COUNT; i++) {
|
||||
uart_port_context_t *ctx = &g_port_ctx[i];
|
||||
|
||||
ctx->huart = g_port_uart_map[i];
|
||||
ctx->name = g_port_name_map[i];
|
||||
|
||||
rx_ring_init(&ctx->rx_ring);
|
||||
tx_ring_init(&ctx->tx_ring);
|
||||
|
||||
ctx->rx_tmp = 0;
|
||||
ctx->rx_count = 0;
|
||||
ctx->tx_count = 0;
|
||||
ctx->error_count = 0;
|
||||
ctx->initialized = true;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Init OK, %d ports configured", PORT_COUNT);
|
||||
}
|
||||
|
||||
void MultiUART_FeedByte(port_id_t port_id, uint8_t byte)
|
||||
{
|
||||
// DEBUG_LOG("FeedByte: %02X", byte);
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_port_context_t *ctx = &g_port_ctx[port_id];
|
||||
|
||||
if (!ctx->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rx_ring_push(&ctx->rx_ring, byte)) {
|
||||
ctx->error_count++;
|
||||
DEBUG_LOG("%s RX overflow", ctx->name);
|
||||
}
|
||||
|
||||
ctx->rx_count++;
|
||||
}
|
||||
|
||||
void MultiUART_Task(void)
|
||||
{
|
||||
for (port_id_t i = 0; i < PORT_COUNT; i++) {
|
||||
uart_port_context_t *ctx = &g_port_ctx[i];
|
||||
|
||||
if (!ctx->initialized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == PORT_UART2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tx_kickoff(i);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUART_Send(port_id_t port_id, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (port_id >= PORT_COUNT || data == NULL || len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (port_id == PORT_UART2) {
|
||||
UART2_Print_Send(data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
uart_port_context_t *ctx = &g_port_ctx[port_id];
|
||||
|
||||
if (!ctx->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t written = tx_ring_push(&ctx->tx_ring, data, len);
|
||||
|
||||
if (written > 0) {
|
||||
ctx->tx_count += written;
|
||||
tx_kickoff(port_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUART_SendString(port_id_t port_id, const char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return;
|
||||
}
|
||||
MultiUART_Send(port_id, (const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
void MultiUART_SendFmt(port_id_t port_id, const char *fmt, ...)
|
||||
{
|
||||
if (fmt == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
int len = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (len > 0) {
|
||||
if (len >= (int)sizeof(buffer)) {
|
||||
len = sizeof(buffer) - 1;
|
||||
}
|
||||
MultiUART_Send(port_id, (const uint8_t *)buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUART_TxCpltCallback(port_id_t port_id)
|
||||
{
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (port_id == PORT_UART2) {
|
||||
UART2_Print_TxCpltCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
uart_port_context_t *ctx = &g_port_ctx[port_id];
|
||||
uart_tx_ring_t *ring = &ctx->tx_ring;
|
||||
uint8_t byte;
|
||||
bool has_more = false;
|
||||
|
||||
__disable_irq();
|
||||
ring->is_sending = false;
|
||||
|
||||
if (ring->count > 0) {
|
||||
byte = ring->buffer[ring->tail];
|
||||
ring->tail = (ring->tail + 1) % UART_TX_BUFFER_SIZE;
|
||||
ring->count--;
|
||||
ring->is_sending = true;
|
||||
has_more = true;
|
||||
}
|
||||
__enable_irq();
|
||||
|
||||
if (has_more) {
|
||||
HAL_UART_Transmit_IT(ctx->huart, &byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const char *MultiUART_GetPortName(port_id_t port_id)
|
||||
{
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return g_port_name_map[port_id];
|
||||
}
|
||||
|
||||
uint16_t MultiUART_GetRxCount(port_id_t port_id)
|
||||
{
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t count;
|
||||
__disable_irq();
|
||||
count = g_port_ctx[port_id].rx_ring.count;
|
||||
__enable_irq();
|
||||
return count;
|
||||
}
|
||||
|
||||
uint16_t MultiUART_ReadByte(port_id_t port_id, uint8_t *byte)
|
||||
{
|
||||
if (port_id >= PORT_COUNT || byte == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uart_rx_ring_t *ring = &g_port_ctx[port_id].rx_ring;
|
||||
|
||||
__disable_irq();
|
||||
if (ring->count == 0) {
|
||||
__enable_irq();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*byte = ring->buffer[ring->tail];
|
||||
ring->tail = (ring->tail + 1) % UART_RX_BUFFER_SIZE;
|
||||
ring->count--;
|
||||
__enable_irq();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t MultiUART_GetTxAvailable(port_id_t port_id)
|
||||
{
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t available;
|
||||
__disable_irq();
|
||||
available = UART_TX_BUFFER_SIZE - g_port_ctx[port_id].tx_ring.count;
|
||||
__enable_irq();
|
||||
return available;
|
||||
}
|
||||
|
||||
uint32_t MultiUART_GetOverflowCount(port_id_t port_id)
|
||||
{
|
||||
if (port_id >= PORT_COUNT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_port_ctx[port_id].rx_ring.overflow_count +
|
||||
g_port_ctx[port_id].tx_ring.overflow_count;
|
||||
}
|
||||
Reference in New Issue
Block a user