[APM32F1]

如果APM32F107串口中断接收丢包现象成立,那么可能的解决方法分析

[复制链接]
552|8
手机看帖
扫描二维码
随时随地手机跟帖
丙丁先生|  楼主 | 2025-4-25 21:34 | 显示全部楼层 |阅读模式
如果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();}解释


在APM32F107微控制器上,串口同时进行发送和接收时出现接收丢包的问题,具体表现为偶发进入串口接收中断但`USART_FLAG_RXBNE`标志位未触发,导致无法读取到该字节。以下是对问题的详细解释及可能的解决方案:

问题描述
1. 现象:在串口同时发送和接收数据时,接收端偶尔会丢失字节。具体表现为进入接收中断的次数与实际应接收的字节数一致,但有时`USART_FLAG_RXBNE`标志位未被触发,导致无法读取到该字节。
2. 排查结果:
   发送是阻塞式发送,没有使用发送中断,排除了进入发送中断的可能性。
   其他溢出及错误标志位(如`USART_FLAG_OVRE`)未被置位。
   代码中没有在其他地方主动调用`USART_RxData`读取数据。
   串口中断优先级已调至最高。
   只接收不发送时不会丢字节,挂一晚上都不丢,只要一发送接收就会丢。

可能的原因
1. 发送和接收冲突:在阻塞式发送过程中,可能会占用串口资源,导致接收中断无法及时响应。
2. 中断处理时间过长:如果接收中断处理函数执行时间过长,可能会导致后续的接收中断被延迟或丢失。
3. 硬件资源竞争:发送和接收操作可能涉及到相同的硬件资源(如DMA通道、缓冲区等),导致资源竞争。
4. 时钟配置问题:串口的时钟配置可能不稳定,导致在高负载下出现异常。
5. 软件逻辑问题**:接收中断处理函数中的逻辑可能存在问题,导致某些情况下无法正确处理接收数据。

解决方案
1. 优化发送方式:
    考虑使用非阻塞式发送或发送中断,避免在发送过程中长时间占用串口资源。
    确保发送完成后再进行接收操作,避免资源竞争。

2. 缩短中断处理时间:
    尽量简化接收中断处理函数中的代码,减少不必要的操作。
    如果需要执行复杂操作,可以将数据放入缓冲区,在主循环中处理。

3. 检查硬件资源:
    确保发送和接收操作使用不同的DMA通道或缓冲区,避免资源竞争。
    检查串口的时钟配置,确保在高负载下稳定运行。

4. 增加错误处理:
    在接收中断处理函数中增加对`USART_FLAG_OVRE`等错误标志位的处理,确保在发生错误时能够及时恢复。
    定期检查串口状态,确保通信正常。

5. 调试和日志:
   在关键位置添加日志输出,记录发送和接收的状态,帮助定位问题。
   使用示波器或逻辑分析仪检查串口信号,确保硬件连接正常。

示例代码优化
```c
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();
}
```
总结
通过优化发送方式、缩短中断处理时间、检查硬件资源、增加错误处理以及调试和日志记录,可以有效解决APM32F107在串口同时发送和接收时出现的接收丢包问题。

使用特权

评论回复
lemonboard| | 2025-4-26 20:03 | 显示全部楼层
这个是AI上传上来的解答吗?

使用特权

评论回复
心跳回响| | 2025-4-27 10:51 | 显示全部楼层
如果上流程上面的问题,出现概率应该比较大。
感觉是哪里撞车了,只是没有考虑到

使用特权

评论回复
快乐制造机| | 2025-4-27 15:49 | 显示全部楼层
这种情况确实棘手,通常需要检查硬件连接和软件配置。你的排查很全面,可以尝试优化中断服务程序,减少处理时间,看是否有改善。

使用特权

评论回复
丙丁先生|  楼主 | 2025-4-27 19:15 | 显示全部楼层
lemonboard 发表于 2025-4-26 20:03
这个是AI上传上来的解答吗?

使用特权

评论回复
丙丁先生|  楼主 | 2025-4-27 19:15 | 显示全部楼层
心跳回响 发表于 2025-4-27 10:51
如果上流程上面的问题,出现概率应该比较大。
感觉是哪里撞车了,只是没有考虑到 ...

感谢回复。

使用特权

评论回复
丙丁先生|  楼主 | 2025-4-27 19:16 | 显示全部楼层
快乐制造机 发表于 2025-4-27 15:49
这种情况确实棘手,通常需要检查硬件连接和软件配置。你的排查很全面,可以尝试优化中断服务程序,减少处理 ...

感谢回复。

使用特权

评论回复
丙丁先生|  楼主 | 2025-4-27 19:18 | 显示全部楼层
根据AI的结论,一步步排查,总能解决问题,这样的过程我屡试不爽。毕竟AI已经读遍世界上所有的书了。

使用特权

评论回复
Alden| | 2025-4-30 09:43 | 显示全部楼层
用DMA和空闲中断可能会好有点

使用特权

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

本版积分规则

999

主题

3632

帖子

5

粉丝