STM32
直播中

陈杰

8年用户 1504经验值
私信 关注
[问答]

STM32F103长时间运行,串口发送失败怎么解决?

STM32F103长时间运行,串口发送失败,目前定位到一致卡在USART_FLAG_TC判断那里,我们采用轮询的方式发送数据,然后判断USART_FLAG_TC是否发送成功,在大量发送后出现了一次发送后USART_FLAG_TC没有置位,然后就一直卡在这里了,这可如何是好?

回帖(1)

王璐

2025-8-4 17:36:41

问题分析与解决方案


在STM32F103长时间运行后串口发送卡在USART_FLAG_TC标志判断处,通常是串口状态机异常错误标志未清除硬件不稳定导致。以下是逐步解决方案:




1. 加入超时退出机制


在轮询等待标志时必须添加超时处理,避免死锁:


#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);
}



2. 错误状态恢复机制


超时后清除错误标志并软复位串口:


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);  // 重新初始化波特率等参数
}



3. 确保串口初始化的正确性


检查初始化代码:



  • 时钟配置:启用USART和对应GPIO的时钟。

  • 引脚复用:正确配置TX/RX引脚为复用推挽输出。

  • 波特率计算:使用标准公式(避免浮点误差):
    USARTx->BRR = (pclk + (baudrate / 2)) / baudrate;




4. 排查硬件问题



  • 电源稳定性:用示波器检查MCU供电电压(3.3V是否稳定)。

  • 晶振干扰:长时间运行时时钟源是否稳定(HSE/LSI)。

  • 信号干扰:TX线上串联22Ω电阻+对地33pF电容滤波。

  • 热稳定性:高温环境下芯片是否过热(超过85℃需散热)。




5. 替代方案:中断发送


改用中断驱动发送,减少轮询阻塞风险:


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;
}



6. 系统级稳定性增强



  • 看门狗:启用独立看门狗(IWDG)复位整个系统:
    IWDG->KR = 0xCCCC;  // 启动看门狗
    while (1) {
      IWDG->KR = 0xAAAA;  // 喂狗(在主循环中)
    }

  • 内存校验:定期检查栈溢出(例如使用0xDEADBEEF填充栈底)。




总结建议



  1. 立即修复:添加超时和软复位(步骤1+2),可解决90%的卡死问题。

  2. 长期加固

    • 改用中断+DMA发送

    • 启用看门狗

    • 定期监控串口错误标志


  3. 测试方案:用信号发生器模拟干扰,测试错误恢复流程的健壮性。



关键点USART_FLAG_TC未置位通常是硬件错误标志未清除(如ORE),导致状态机锁死。强制清除错误后复位串口是最直接有效的恢复手段。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分