Files
433_STM32/Core/Src/uart2_print.c
zhongxuanzhen 71027ebc46 3.27_433:添加UART2调试打印、IO监控、指令解析和继电器控制模块。
能够接收UART2指令控制继电器开关,或向UART2发送四路IO输入状态,并使用轮询方式检测IO状态进行及时反馈。
2026-03-27 10:09:13 +08:00

225 lines
5.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 uart2_print.c
* @brief UART2调试打印模块实现
* @author Application Layer
* @version 1.1
******************************************************************************
* @attention
* 本模块实现基于环形缓冲区的非阻塞调试信息输出
* 关键特性:
* 1. 环形缓冲区避免数据丢失
* 2. 中断安全支持ISR中调用
* 3. 非阻塞发送,不影响实时性
*
* 修订历史:
* v1.1 - 修复审查报告高危-1/2/3中危-4
******************************************************************************
*/
#include "uart2_print.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
#define DEBUG_PRINT_ENABLED 1
#if DEBUG_PRINT_ENABLED
#define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[UART2] " fmt "\r\n", ##__VA_ARGS__)
#else
#define DEBUG_LOG(fmt, ...)
#endif
typedef struct {
uint8_t buffer[UART2_TX_BUFFER_SIZE];
volatile uint16_t head;
volatile uint16_t tail;
volatile uint16_t count;
volatile bool is_sending;
volatile uint16_t overflow_count;
} ring_buffer_t;
static ring_buffer_t tx_ring = {0};
void UART2_Print_Init(void)
{
tx_ring.head = 0;
tx_ring.tail = 0;
tx_ring.count = 0;
tx_ring.is_sending = false;
tx_ring.overflow_count = 0;
DEBUG_LOG("Init OK, buffer size: %d", UART2_TX_BUFFER_SIZE);
}
void UART2_Print_Send(const uint8_t *data, uint16_t len)
{
if (len == 0 || data == NULL) {
return;
}
uint16_t written = 0;
bool needs_kickoff = false;
__disable_irq();
for (uint16_t i = 0; i < len; i++) {
if (tx_ring.count >= UART2_TX_BUFFER_SIZE) {
tx_ring.overflow_count++;
break;
}
tx_ring.buffer[tx_ring.head] = data[i];
tx_ring.head = (tx_ring.head + 1) % UART2_TX_BUFFER_SIZE;
tx_ring.count++;
written++;
}
if (written > 0 && !tx_ring.is_sending) {
tx_ring.is_sending = true;
needs_kickoff = true;
}
__enable_irq();
if (needs_kickoff) {
uint8_t byte;
__disable_irq();
byte = tx_ring.buffer[tx_ring.tail];
__enable_irq();
HAL_UART_Transmit_IT(&huart2, &byte, 1);
}
}
void UART2_Print_String(const char *str)
{
if (str == NULL) {
return;
}
UART2_Print_Send((const uint8_t *)str, strlen(str));
}
void UART2_Print_Printf(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;
}
UART2_Print_Send((const uint8_t *)buffer, len);
}
}
void UART2_Print_Task(void)
{
uint8_t byte;
uint16_t current_tail;
__disable_irq();
if (tx_ring.is_sending || tx_ring.count == 0) {
__enable_irq();
return;
}
current_tail = tx_ring.tail;
tx_ring.tail = (tx_ring.tail + 1) % UART2_TX_BUFFER_SIZE;
tx_ring.count--;
tx_ring.is_sending = true;
byte = tx_ring.buffer[current_tail];
__enable_irq();
HAL_UART_Transmit_IT(&huart2, &byte, 1);
}
void UART2_Print_TxCpltCallback(void)
{
uint8_t byte;
uint16_t current_tail;
bool has_more = false;
__disable_irq();
tx_ring.is_sending = false;
if (tx_ring.count > 0) {
current_tail = tx_ring.tail;
tx_ring.tail = (tx_ring.tail + 1) % UART2_TX_BUFFER_SIZE;
tx_ring.count--;
tx_ring.is_sending = true;
byte = tx_ring.buffer[current_tail];
has_more = true;
}
__enable_irq();
if (has_more) {
HAL_UART_Transmit_IT(&huart2, &byte, 1);
}
}
bool UART2_Print_IsBusy(void)
{
bool busy;
__disable_irq();
busy = tx_ring.is_sending || (tx_ring.count > 0);
__enable_irq();
return busy;
}
uint16_t UART2_Print_Available(void)
{
uint16_t available;
__disable_irq();
available = UART2_TX_BUFFER_SIZE - tx_ring.count;
__enable_irq();
return available;
}
uint16_t UART2_Print_GetOverflowCount(void)
{
return tx_ring.overflow_count;
}
/**
* @brief printf重定向函数 (Keil MDK)
* @note 重定向标准库printf到UART2
* @param ch: 待发送字符
* @param f: 文件指针(未使用)
* @retval 发送的字符
*/
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
int fputc(int ch, FILE *f)
{
(void)f;
UART2_Print_Send((uint8_t *)&ch, 1);
return ch;
}
#endif
/**
* @brief printf重定向函数 (GCC)
* @note 重定向标准库printf到UART2
* @param ch: 待发送字符
* @retval 发送的字符
*/
#if defined(__GNUC__)
int __io_putchar(int ch)
{
UART2_Print_Send((uint8_t *)&ch, 1);
return ch;
}
int _write(int file, char *ptr, int len)
{
(void)file;
UART2_Print_Send((uint8_t *)ptr, len);
return len;
}
#endif