在STM32F103长时间运行后串口发送卡在USART_FLAG_TC标志判断处,通常是串口状态机异常、错误标志未清除或硬件不稳定导致。以下是逐步解决方案:
在轮询等待标志时必须添加超时处理,避免死锁:
#define USART_TIMEOUT 1000 // 根据波特率调整(例如1ms)
void USART_SendData(USART_TypeDef* USARTx, uint8_t *data, uint16_t len) {
for (uint16_t i = 0; i < len; i++) {
// 等待TXE(发送寄存器空)
uint32_t timeout = USART_TIMEOUT;
while (!(USARTx->SR & USART_SR_TXE) && --timeout);
if (!timeout) goto ErrorHandler; // 超时处理
USARTx->DR = data[i]; // 写入数据
// 等待TC(发送完成)
timeout = USART_TIMEOUT;
while (!(USARTx->SR & USART_SR_TC) && --timeout);
if (!timeout) goto ErrorHandler; // 超时处理
}
return;
ErrorHandler:
// 进入错误恢复流程(见步骤2)
USART_Recover(USARTx);
}超时后清除错误标志并软复位串口:
void USART_Recover(USART_TypeDef* USARTx) {
// 1. 清除所有错误标志(ORE/FE/NE)
(void)USARTx->SR; // 读SR寄存器
(void)USARTx->DR; // 读DR寄存器(重要!清除锁定状态)
// 2. 软复位串口
USARTx->CR1 &= ~USART_CR1_UE; // 关闭串口
USARTx->CR1 |= USART_CR1_UE; // 重新使能串口
// 3. 重新配置串口(可选)
USART_Init(USARTx, &usart_config); // 重新初始化波特率等参数
}检查初始化代码:
USARTx->BRR = (pclk + (baudrate / 2)) / baudrate;改用中断驱动发送,减少轮询阻塞风险:
volatile uint8_t tx_complete = 0;
void USARTx_IRQHandler(void) {
if (USARTx->SR & USART_SR_TC) {
tx_complete = 1;
USARTx->CR1 &= ~USART_CR1_TCIE; // 关闭TC中断
}
}
void USART_SendIT(uint8_t *data, uint16_t len) {
// ... 启动发送第一个字节
USARTx->CR1 |= USART_CR1_TCIE; // 开启TC中断
while (!tx_complete); // 等待中断置位标志
tx_complete = 0;
}IWDG->KR = 0xCCCC; // 启动看门狗
while (1) {
IWDG->KR = 0xAAAA; // 喂狗(在主循环中)
}0xDEADBEEF填充栈底)。
关键点:
USART_FLAG_TC未置位通常是硬件错误标志未清除(如ORE),导致状态机锁死。强制清除错误后复位串口是最直接有效的恢复手段。
举报
更多回帖