You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F091 USART3接收GPS数据时环形缓冲区字符重复写入问题

问题分析与修复方案

嘿,我看你遇到的核心问题是GPS字符被重复写入环形缓冲区,而转发到PC的功能却正常——这大概率是USART3中断处理函数里的逻辑错误导致的,下面给你一步步拆解和修复:

1. 最关键的错误:中断触发条件判断完全写错了

你现在代码里的判断是:

if (USART_FLAG_RXNE != RESET)

这可不对啊!USART_FLAG_RXNE是个固定的掩码常量(比如STM32F0里它是0x0020),永远不可能等于RESET(0),所以这个条件永远为真。只要USART3的中断被触发(比如溢出错误、或者其他残留的标志),不管有没有新的GPS数据,你都会去读USART3的DR寄存器——如果没有新数据,就会重复读同一个已经接收的字符,自然就会在环形缓冲区里出现一堆重复的G、P、S了。

怎么改?

换成正确的标志位状态检查,用USART_GetFlagStatus函数判断RXNE标志是否真的置位了:

if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) != RESET)

2. 溢出错误(ORE)的处理方式不对

你代码里用USART_GetITStatus(USART3, USART_IT_ORE);处理溢出,但这个函数只是返回状态,不会清除ORE标志。如果ORE标志没被清掉,会一直触发中断,进一步让重复读取的问题更严重。

根据STM32F0的手册,清除ORE标志的正确步骤是先读SR寄存器,再读DR寄存器。所以你可以改成:

// 先检查并处理溢出错误
if (USART_GetFlagStatus(USART3, USART_FLAG_ORE) != RESET)
{
    // 读SR和DR来清除ORE标志,用(void)避免编译器警告
    (void)USART3->SR;
    (void)USART3->DR;
}

3. 别忘了检查环形缓冲区的初始化

你得确保RXD_uart_3的max成员被正确设为255(也就是缓冲区的大小),还有re和wr初始化为0,pRXD3指向正确的结构体。如果max设错了,比如设成0,那wr的取模计算会出问题,虽然这不是当前重复字符的直接原因,但后续可能出其他bug。

初始化代码可以放在main函数里:

RXD_uart_3.max = 255;
RXD_uart_3.re = 0;
RXD_uart_3.wr = 0;
pRXD3 = &RXD_uart_3;

4. USART1发送逻辑可以优化一下(可选)

你现在的发送代码里,USART_GetITStatus(USART1, USART_IT_TC);这行其实没什么用,它只是检查TC标志,没做任何处理。发送数据前最好等TXE(发送寄存器空)标志,避免覆盖还没发完的数据。虽然你说转发功能正常,但改了之后更健壮:

// 等USART1的发送寄存器空了再发
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, byte);

修复后的完整中断函数

把上面的修改整合起来,中断函数就变成这样了:

#include <main.h>

void USART3_8_IRQHandler(void)
{
    // 先处理溢出错误,防止持续触发中断
    if (USART_GetFlagStatus(USART3, USART_FLAG_ORE) != RESET)
    {
        (void)USART3->SR;
        (void)USART3->DR;
    }

    // 确认有新的接收数据再处理
    if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) != RESET)
    {
        uint16_t byte = USART_ReceiveData(USART3);

        // 写入环形缓冲区
        (*pRXD3).wr = ((*pRXD3).wr + 1) % (*pRXD3).max;
        (*pRXD3).Buffer[(*pRXD3).wr] = byte;

        // 转发到PC的USART1
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, byte);
    }
    return;
}

最后验证一下

烧录修改后的代码,先看环形缓冲区里的数据是不是正常了(没有重复字符),再用u-center确认转发到PC的GPS数据还是正常的,这样就没问题啦。

内容的提问来源于stack exchange,提问作者Kater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:21:57