21ic电子技术开发论坛

标题: APM32F107串口中断接收丢包 [打印本页]

作者: xiaoqilo    时间: 2025-4-24 09:54
标题: APM32F107串口中断接收丢包
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
作者: 风暴之眸    时间: 2025-4-24 14:41
我不是技术支持。版主们应该是!
作者: Gfan    时间: 2025-4-24 18:00
这部分代码看不出问题噢,需要更多的代码内容才能分析

建议先排查两个方面:


作者: jobszheng    时间: 2025-4-25 19:03
这个真心没有遇到过。
我们使用的是应答方式来通讯。直接全双工的方式,还真没有实践过
作者: xiaoqilo    时间: 2025-4-26 11:28
更神奇的是我用STM32F107的例程代码就没问题,APM的例程和STM的例程都已经删除的只剩串口部分了,没有其他代码,HCLK、PCLK时钟也检查了完全一致,串口寄存器值也完全一致
作者: xiaoqilo    时间: 2025-4-26 11:33
Gfan 发表于 2025-4-24 18:00
这部分代码看不出问题噢,需要更多的代码内容才能分析

建议先排查两个方面:

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

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

这个真心没有遇到过。不过丢包影响很大么。大数据量丢一两个也是很正常啊,或者你开开奇偶校验事实。
作者: lemonboard    时间: 2025-4-26 20:02
感觉这个bug还有点严重,不过倒是可以通过对数据帧添加校验来workaround掉。

作者: 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的库?
作者: Gfan    时间: 2025-4-29 10:05
本帖最后由 Gfan 于 2025-4-29 10:35 编辑
xiaoqilo 发表于 2025-4-26 20:24
解决了,库函数有问题:
void USART_TxData(USART_T* usart, uint16_t data)
{

你好呀,我们尝试复现问题,但使用我们的SDK,并未出现丢包情况,是否方便提供更多信息,以便定位问题呢? 36517681030f5565c5.png




作者: 1988020566    时间: 2025-5-6 09:25
串口通信线路可能受到周围环境中的电磁干扰
作者: mnynt121    时间: 2025-5-6 10:24
确认发送端和接收端的波特率设置一致,并且是双方都支持的标准值。
作者: saservice    时间: 2025-5-6 11:38
中断服务函数执行时间过长              
作者: nomomy    时间: 2025-5-6 12:57
优化中断服务函数的代码,尽量减少不必要的操作。
作者: ulystronglll    时间: 2025-5-6 14:43
使用环形缓冲区              
作者: ingramward    时间: 2025-5-6 16:57
检查地线是否完整,避免共模干扰。
作者: jobszheng    时间: 2025-5-6 17:46
都是32位的地址寻址,读9位和读32位应该是一样的呀!
作者: uytyu    时间: 2025-5-6 18:44
如果串口中断的优先级设置过低,在高负载情况下可能会被其他更高优先级的中断打断,导致来不及处理接收到的数据。
作者: tifmill    时间: 2025-5-6 20:27
考虑使用非阻塞式发送或发送中断,避免在发送过程中长时间占用串口资源。
作者: tabmone    时间: 2025-5-6 22:10
检查晶振的参数是否符合 APM32F107 的要求,确保晶振的频率精度和稳定性。
作者: claretttt    时间: 2025-5-11 10:36
如果单片机的时钟源不够稳定,可能会影响串口通信的准确性。
作者: robertesth    时间: 2025-5-11 12:17
串口的时钟配置可能不稳定,导致在高负载下出现异常。
作者: adolphcocker    时间: 2025-5-11 17:05
如果接收缓冲区的大小不够,当接收到的数据量超过缓冲区的容量时,新的数据会覆盖之前未处理的数据,导致丢包。
作者: lzbf    时间: 2025-5-13 15:47
检查并调整串口中断的优先级,确保它具有足够的优先级来及时处理接收到的数据。
作者: bartonalfred    时间: 2025-5-13 17:51
尽量缩短通信线路的长度,避免信号线靠近强干扰源。
作者: modesty3jonah    时间: 2025-5-13 20:04
如果接收缓冲区太小,当数据到达速率超过应用程序处理速率时,可能导致数据溢出丢失。
作者: mollylawrence    时间: 2025-5-14 21:03
串口通信的波特率依赖于系统时钟和晶振的稳定性。如果晶振频率不准确或不稳定,会导致波特率误差,从而使接收端无法正确解析数据,造成丢包。
作者: zhengshuai888    时间: 2025-5-14 21:19
多半是数据接收处理逻辑存在问题导致的
作者: fengm    时间: 2025-5-15 10:28
检查硬件资源冲突              
作者: i1mcu    时间: 2025-5-15 12:30
外部干扰              
作者: uptown    时间: 2025-5-15 14:23
使用示波器或逻辑分析仪验证实际波特率。
作者: uiint    时间: 2025-5-15 16:10
在代码中仔细检查波特率的配置参数,使用相同的波特率值进行初始化。
作者: ccook11    时间: 2025-5-15 17:55
使用两组缓冲区交替接收数据,避免数据处理延迟导致丢包。
作者: everyrobin    时间: 2025-5-15 19:38
尽量减少ISR内的工作量,只做必要的处理(如将数据存入环形缓冲区),并将复杂的处理逻辑移到主循环中执行。
作者: zerorobert    时间: 2025-5-15 21:20
缓冲区过小或数据处理速度慢,导致数据覆盖。
作者: jtracy3    时间: 2025-5-16 10:51
可以在串口通信线路上添加滤波电容,滤除高频干扰信号。
作者: hudi008    时间: 2025-5-16 12:33
在阻塞式发送过程中,可能会占用串口资源,导致接收中断无法及时响应。
作者: eefas    时间: 2025-5-16 14:28
增大接收缓冲区的大小,确保缓冲区能够容纳足够的数据。可以使用环形缓冲区来实现数据的循环存储,避免数据覆盖。同时,在处理缓冲区数据时,要及时清除已经处理的数据,以腾出空间接收新的数据。
作者: adolphcocker    时间: 2025-5-16 16:26
接收中断处理函数中的逻辑可能存在问题,导致某些情况下无法正确处理接收数据。
作者: 10299823    时间: 2025-5-16 18:22
发送端和接收端的波特率设置不一致会导致数据传输错误,接收端无法正确解析数据,从而出现丢包现象。
作者: janewood    时间: 2025-5-16 20:04
如果接收中断处理函数执行时间过长,可能会导致后续的接收中断被延迟或丢失。
作者: mnynt121    时间: 2025-5-16 21:46
如果ISR内部执行了过多的操作或等待操作,会导致无法及时响应新的中断请求,从而造成数据丢失。
作者: earlmax    时间: 2025-5-21 10:16
使用DMA减少CPU中断频率,提高吞吐量。
作者: robertesth    时间: 2025-5-21 12:50
发送和接收操作可能涉及到相同的硬件资源(如DMA通道、缓冲区等),导致资源竞争。
作者: everyrobin    时间: 2025-5-21 14:34
串口信号线未加磁珠/滤波电容,导致数据错误。
作者: houjiakai    时间: 2025-5-21 16:19
其他高优先级中断抢占串口中断,导致数据接收延迟。
作者: youtome    时间: 2025-5-21 18:12
ISR内执行复杂操作(如数据解析),阻塞后续中断响应。
作者: belindagraham    时间: 2025-5-21 20:02
物理连接不良、噪声干扰等问题也可能导致数据传输错误或丢失。
作者: janewood    时间: 2025-5-21 22:02
错误的波特率设置会导致发送端与接收端之间的通信不匹配,进而引起数据丢失或乱码。
作者: updownq    时间: 2025-5-23 09:24
对于大数据量传输,建议使用DMA或环形缓冲区,减少中断频率,降低CPU负载。例如,配置DMA接收数据到缓冲区,由主循环处理数据。
作者: elsaflower    时间: 2025-5-23 11:15
增加接收缓冲区的大小,或者实现一种机制来动态调整缓冲区大小以适应不同的数据流速率。
作者: hilahope    时间: 2025-5-23 13:06
如果串口中断服务函数中包含过多的操作或耗时的代码,会导致中断服务函数执行时间过长,从而影响下一次数据的接收。在中断服务函数执行期间,新的数据可能会覆盖之前未处理的数据,导致丢包。
作者: i1mcu    时间: 2025-5-23 14:53
中断标志未清除导致重复进入中断或数据丢失。
作者: uptown    时间: 2025-5-23 16:37
可以将一些耗时的操作放到主循环中处理,只在中断服务函数中进行数据的简单接收和标记
作者: biechedan    时间: 2025-5-23 18:19
不稳定的电源可能导致串口通信芯片工作异常,影响数据的正常接收。电源电压波动过大、电源纹波过大等都可能引起丢包问题。
作者: beacherblack    时间: 2025-5-23 20:18
在每次读取数据后,立即清除RXNE标志。
作者: hudi008    时间: 2025-5-23 22:07
改用非阻塞式发送或发送中断,避免在发送过程中长时间占用串口资源。例如,在发送完成后触发中断,释放资源供接收使用。
作者: macpherson    时间: 2025-5-24 10:10
对串口通信线路进行屏蔽处理,使用屏蔽线可以有效减少电磁干扰。
作者: sdlls    时间: 2025-5-24 12:51
过长的通信线路也会增加信号衰减和干扰的风险。
作者: 星云狂想曲    时间: 2025-5-29 16:25
串口的通讯压力并不大吧
作者: 分形梦想家    时间: 2025-5-30 17:31
这种情况是不是使用DMA接收会好很多啊




欢迎光临 21ic电子技术开发论坛 (https://bbs.21ic.com/) Powered by Discuz! X3.5