打印

APM32F107串口中断接收丢包

[复制链接]
501|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaoqilo|  楼主 | 2025-4-24 09:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
APM32F107在串口同时发送和接收的情况下串口接收丢字节,具体表现为偶发进入串口接收中断了,但是USART_FLAG_RXBNE标志位没有触发,导致读不到这个字节进而丢字节,通过计数发现进入中断的次数与实际应该收到的字节数一致。1、发送是阻塞式发送的,没有用发送中断,排除进入的是发送中断的可能。
2、出现这种情况时打断点看了,其他的溢出及错误标志位并没有置位,也打印检查了,没有置位。
3、排查代码了没有在其他地方主动调用USART_RxDatad读取。
4、串口中断优先级已调至最高。
5、只接收不发送不会丢字节,挂一晚上都不丢,只要一发送接收就会丢。

发送代码:
void Uart1_Send(char buf)
{
    uint16_t data_9th = buf;
    dog_feed_count_clean(); // 循环清除喂狗变量,超过DOG_PROTECT_TIME_100MS不清除则认为主循环异常,并停止喂狗。
    if (g_rParameters.sPort[0].ucParity == UART_CHK_MARK)
    {
        data_9th |= (1 << (uart1_data_bit - 1));
    }
    else if (g_rParameters.sPort[0].ucParity == UART_CHK_SPACE)
    {
        data_9th &= ~(1 << (uart1_data_bit - 1));
    }

    WAIT_TX_EMPTY; // wait data register empty//等待发送完
    USART_TxData(USART1, data_9th);
}


接收中断:
void USART1_IRQHandler(void)
{
    uint8_t data;
    uint8_t longth = g_sParameters.sPort[0].ucDataSize;
    if (USART_ReadStatusFlag(USART1, USART_FLAG_OVRE) == SET)
    {
        // 由软件清0,先读取USART_STS寄存器,再读USART_DATA寄存器完成清0。
        USART_RxData(USART1);
    }
    if (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == SET)
    {
        data = (uint8_t)USART_RxData(USART1); // fetch recv data from buffer
        if (g_sParameters.sPort[0].ucParity != UART_CHK_NONE)
        {
            data = data & (~(1 << longth)); // 去掉校验位
        }
        if (AtCmd_enter_mode(0, data) == 1)
        {
            packet_count = 0;
        }
        else
        {
            packet_count = 0;
            uart1_rx_ringbuf_push(&uart1_rx_ringbuf, data);
            // uart_rec_len ++;
        }
        usart_recv_total_len++;
    }
    timer_pack_reset_func();
}


使用特权

评论回复
沙发
风暴之眸| | 2025-4-24 11:29 | 只看该作者
感觉应该不会呀!
F107的主频近百兆呢!处理一个kbps级别的通讯。
即使错误进入了串口接收中断了,只要没有读出 ,下次仍然会进入串口中断

使用特权

评论回复
板凳
xiaoqilo|  楼主 | 2025-4-24 11:44 | 只看该作者
风暴之眸 发表于 2025-4-24 11:29
感觉应该不会呀!
F107的主频近百兆呢!处理一个kbps级别的通讯。
即使错误进入了串口接收中断了,只要没有 ...

你是极海的技术支持么?

使用特权

评论回复
地板
伏尔加的鱼| | 2025-4-24 12:44 | 只看该作者
检查你其它地方程序吧  不知道你波特率用的多少我115200的很多都是中断收发也没出现大概率的丢包,不行你就上DMA

使用特权

评论回复
5
风暴之眸| | 2025-4-24 14:41 | 只看该作者
我不是技术支持。版主们应该是!

使用特权

评论回复
6
Gfan| | 2025-4-24 18:00 | 只看该作者
这部分代码看不出问题噢,需要更多的代码内容才能分析

建议先排查两个方面:
  • 中断处理函数中清除过载标志在判断接收buff非空之前,是否已经发生过载,但被清除。
  • 检查发送速度和接收速度是否一致,如果发送和接收时的速度不一致,可能导致数据丢失。

使用特权

评论回复
7
jobszheng| | 2025-4-25 19:03 | 只看该作者
这个真心没有遇到过。
我们使用的是应答方式来通讯。直接全双工的方式,还真没有实践过

使用特权

评论回复
8
xiaoqilo|  楼主 | 2025-4-26 11:28 | 只看该作者
更神奇的是我用STM32F107的例程代码就没问题,APM的例程和STM的例程都已经删除的只剩串口部分了,没有其他代码,HCLK、PCLK时钟也检查了完全一致,串口寄存器值也完全一致

使用特权

评论回复
9
xiaoqilo|  楼主 | 2025-4-26 11:33 | 只看该作者
Gfan 发表于 2025-4-24 18:00
这部分代码看不出问题噢,需要更多的代码内容才能分析

建议先排查两个方面:

1、没有,后面我代码修改了,没发现过载
2、波特率是一致的,而且只发送或者只接受都不会有问题

另外我用STM32F107的例程代码就没问题,APM的例程和STM的例程都已经删除的只剩串口部分了,没有其他代码,HCLK、PCLK时钟也检查了完全一致,串口寄存器值也完全一致。

使用特权

评论回复
10
cooldog123pp| | 2025-4-26 14:30 | 只看该作者

这个真心没有遇到过。不过丢包影响很大么。大数据量丢一两个也是很正常啊,或者你开开奇偶校验事实。

使用特权

评论回复
11
lemonboard| | 2025-4-26 20:02 | 只看该作者
感觉这个bug还有点严重,不过倒是可以通过对数据帧添加校验来workaround掉。

使用特权

评论回复
12
xiaoqilo|  楼主 | 2025-4-26 20:24 | 只看该作者
解决了,库函数有问题:
void USART_TxData(USART_T* usart, uint16_t data)
{
    usart->DATA_B.DATA = data;
}
这个DATA_B.DATA只使用了DATA寄存器的9位没使用保留的部分,换为以下方式就没问题
void USART_TxData(USART_T* usart, uint16_t data)
{
    usart->DATA = data;
}
猜测,DATA寄存器会有两个,一个是TX的一个是RX的,但为了兼容性在逻辑地址上是一个,当执行写寄存器操作时会映射到TX的DATA寄存器,执行读操作时映射到RX的DATA寄存器,而官方库这种只操作DATA寄存器一部分bit的写法可能会导致逻辑地址与物理地址的映射错乱,也就造成了只有在发送时才会导致接收丢包这种现象,这只是我的猜测,还得官方解释一下。

不过,这么容易复现的严重问题竟然在官方库出现了,确实不应该啊,而且竟然用ST的库没问题,难道用这个片子的都在用ST的库?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

9

帖子

0

粉丝