打印

APM32F107串口中断接收丢包

[复制链接]
3065|63
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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的库?

使用特权

评论回复
13
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,并未出现丢包情况,是否方便提供更多信息,以便定位问题呢?


  • 您是怎么判断数据丢失的呢?是少了数据个数,还是数据内容有错误?
  • 出错的概率大概是多少?比如是偶尔出现还是比较频繁?
  • 方便的话,能简单说下您的测试方案吗?

使用特权

评论回复
14
1988020566| | 2025-5-6 09:25 | 只看该作者
串口通信线路可能受到周围环境中的电磁干扰

使用特权

评论回复
15
mnynt121| | 2025-5-6 10:24 | 只看该作者
确认发送端和接收端的波特率设置一致,并且是双方都支持的标准值。

使用特权

评论回复
16
saservice| | 2025-5-6 11:38 | 只看该作者
中断服务函数执行时间过长              

使用特权

评论回复
17
nomomy| | 2025-5-6 12:57 | 只看该作者
优化中断服务函数的代码,尽量减少不必要的操作。

使用特权

评论回复
18
ulystronglll| | 2025-5-6 14:43 | 只看该作者
使用环形缓冲区              

使用特权

评论回复
19
ingramward| | 2025-5-6 16:57 | 只看该作者
检查地线是否完整,避免共模干扰。

使用特权

评论回复
20
jobszheng| | 2025-5-6 17:46 | 只看该作者
都是32位的地址寻址,读9位和读32位应该是一样的呀!

使用特权

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

本版积分规则

3

主题

9

帖子

0

粉丝