[应用相关] AT32F403A串口空闲中断多次触发

[复制链接]
6585|12
 楼主| 哪里需要我了 发表于 2025-1-14 15:20 | 显示全部楼层 |阅读模式
本帖最后由 哪里需要我了 于 2025-1-14 16:50 编辑

现在已经实现了带缓冲区的中断收发,这两个中断没啥问题。想空闲中断处理下不定长数据,发现有点不对劲,好像是反复进入中断,改成打印以后确实是这样,明明我测试的数据一秒发送一次,按道理空闲中断不应该一秒触发一次吗?实际打印出来一秒就上千次。
我用的work bench版本是1.1.04,是否要用最新版?
int cnt = 0;
void USART1_IRQHandler(void)
{
        extern QueueHandle_t xQueue_Usart1;
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;  // 声明并初始化xHigherPriorityTaskWoken
        static uint16_t data_len = 0;
        
    uint8_t data;
    uint16_t usedCapacityOfBuffer = 0;
    uint16_t realCountPutBuffer = 0;
        
        if(usart_interrupt_flag_get(USART1, USART_RDBF_FLAG) != RESET) {
        // 获取串口寄存器内数据寄存器的有效数据
                data = usart_data_receive(USART1);
        // 向RX环形缓冲区写入一个字节
                realCountPutBuffer = RingBuf_Put(&s_uart1ReadRingBuffer, &data, 1);
        // 当前环形缓冲区已使用的容量 = 最大值 - 环形缓冲区未使用的大小
        usedCapacityOfBuffer = UART1_READ_BUF_SIZE - RingBuf_GetUnusedSize(&s_uart1ReadRingBuffer);
        // 若 当前环形缓冲区已使用的容量 大于 缓冲区曾经使用过的最大容量,则更新缓冲区曾经使用过的最大容量状态,否则保持原有值
        s_uart1ReadBufferState.maxUsedCapacityOfBuffer =
            usedCapacityOfBuffer > s_uart1ReadBufferState.maxUsedCapacityOfBuffer ? usedCapacityOfBuffer
                                                                                  : s_uart1ReadBufferState.maxUsedCapacityOfBuffer;
        // 向RX环形缓冲区写入一个字节失败,则记录一次失败状态
        s_uart1ReadBufferState.countOfLostData += 1 - realCountPutBuffer;

        // 记录写入RC环形缓冲区内长度累加
        data_len = data_len + realCountPutBuffer;
        }

    if (usart_interrupt_flag_get(USART1, USART_IDLEF_FLAG) != RESET) {
                cnt++;
                printf("cnt = %d\n", cnt);
//                if (xQueueSendFromISR(xQueue_Usart1, &data_len, &xHigherPriorityTaskWoken) == pdPASS) {
//                        // 数据发送成功
//                        data_len = 0;
//                        printf("Data len sent to queue: %d\n", data_len);
//                } else {
//                        // 队列已满,发送失败
//                        printf("Failed to send data to queue.\n");
//                }
                // 如果有更高优先级的任务就绪,请求上下文切换
//                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }

        
        if(usart_interrupt_flag_get(USART1, USART_TDBE_FLAG) != RESET) {
                if (RingBuf_Get(&s_uart1WriteRingBuffer, &data, 1)) {
            // 将一个字节数据写入UART数据寄存器
            usart_data_transmit(USART1, (uint16_t)data);
        } else {
            // 否则关闭串口中断发送
            usart_interrupt_enable(USART1, USART_TDBE_INT, FALSE);
        }
    }
}




Z`R_4Y_J%QWQ04_G6R_$WDB.png
1.png
2.png
 楼主| 哪里需要我了 发表于 2025-1-14 15:30 | 显示全部楼层
请问各位,work bench是如何更新的?这work bench点更新为啥是下载一个zip,是手动解压覆盖吗?旧work bench版本是1.1.04,旧版本的工程迁移到新的work bench上以后有什么注意事项吗?
 楼主| 哪里需要我了 发表于 2025-1-14 15:35 | 显示全部楼层
我看到论坛有个类似帖子,不过是去年九月份的事了
 楼主| 哪里需要我了 发表于 2025-1-14 16:49 | 显示全部楼层
问题已解决,空闲中断需要软件复位,把下面这段加进中断回调函数里面即可
  1. volatile uint32_t temp;
  2. temp = USARTx->STS; // 先读USART状态寄存器
  3. temp = USARTx->DT;  // 再读USART数据寄存器


评论

是的 需要清除标志位  发表于 2025-1-15 16:07
怀揣少年梦 发表于 2025-1-15 09:05 | 显示全部楼层
哪里需要我了 发表于 2025-1-14 15:30
请问各位,work bench是如何更新的?这work bench点更新为啥是下载一个zip,是手动解压覆盖吗?旧w ...

直接覆盖即可。直接使用新版本的软件打开工程即可

评论

好的,感谢回复!  发表于 2025-1-15 18:53
光影捕手 发表于 2025-1-17 17:31 | 显示全部楼层
我也想到了软件清除,很多MCU都是这样
低语之树 发表于 2025-1-21 10:06 | 显示全部楼层
正好也遇到了,看到这个,我就不用发帖问了

评论

多交流学习做记录嘿嘿  发表于 2025-1-21 11:04
旧年胶片 发表于 2025-8-29 14:06 | 显示全部楼层
AT32F403A 串口空闲 中断多次触发,可能是中断清除不彻底,需在处理函数中先读 SR 再读 DR 清除标志。也可能波特率误差大,导致帧同步异常。或接收数据间隔短,被误判为多个空闲帧,可增加帧间隔判断或用 DMA 接收优化。
灵犀幻影 发表于 2025-9-25 09:26 | 显示全部楼层
你的代码中注释掉的部分似乎是用来处理数据长度并发送到队列的
时光贩卖机 发表于 2025-9-26 14:25 | 显示全部楼层
你的代码中打印空闲中断触发次数的逻辑是正确的,但是可能存在硬件或软件层面的问题导致中断标志位没有被正确处理
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

35

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部