STM32串口溢出中断问题
对于STM32F103系列单片机,使能接收中断后,溢出中断就会自动被使能。那什么时候会发生溢出中断呢?在RXNE=1 的的条件下(也就是上次数据还没有读走),串口接收寄存器又接收好了一个字节的数据并准备往RDR 寄存器去转移的时候,会产生溢出中断。产生溢出中断典型的情况有:
1.串口接收中断被更高优先级的中断打断,且打断时间比较长。
2.擦写单片机内部flash时,耗时较长,导致串口中断无法响应。
串口接收的数据越频繁,发生溢出中断的概率越大,如果程序中没有对溢出中断进行处理,就会导致程序死机等情况。
解决办法:
1.判断并清除溢出中断标志。清除溢出标志只需要依次读取SR和DR寄存器即可。在串口中断中添加如下程序:
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_ORE))//溢出标志
{
uint32_t temp = USART1->SR;
temp = USART1->DR;
}
对于使用STM32CubeMX生成的程序,编写串口错误回调函数即可。
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart->ErrorCode & HAL_UART_ERROR_ORE)//溢出错误
{
uint32_t temp = huart->Instance->SR;
temp = huart->Instance->DR;
}
}
2.另外一种方法就是不使能接收中断,比如采用DMA+空闲中断的方式。
那种方法比较好使 当然是DMA比较好啊 中断嵌套:如果串口接收中断被更高优先级的中断(比如定时器中断或其他紧急中断)打断,并且该高优先级中断执行时间较长,那么串口接收中断可能无法在数据到达时及时处理,导致溢出。 Flash写入:在单片机进行内部Flash擦写操作时,会暂时禁止某些中断响应,包括串口接收中断。如果擦写操作时间过长,也可能导致串口接收中断无法及时响应。 因为程序中没有及时处理串口中断吗? 可以在串口接收中断服务程序中添加如下代码来处理溢出错误 直接实用其实也是最好的 这个溢出问题确实坑,我之前就遇到过,特别是高优先级中断占用时间长的时候,RXNE 置位但数据没读走,就容易触发 ORE。 你的解决方案很实用,特别是 if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_ORE)) 这个判断,清除 SR 和 DR 也很关键,不然程序可能会卡住。 采用 DMA+空闲中断确实是个好办法,特别适合高速串口通信,CPU 负担小,而且不会丢数据。 还有一种办法是调高串口中断的优先级,让它优先于大部分中断执行,这样可以降低 ORE 发生的概率。 STM32 的 HAL 库有时候封装太多,底层细节没注意就容易踩坑,手动处理 ORE 确实是必要的。 如果是 F1,USART 是没有 FIFO 的,所以接收数据不能堆积,F4 以上的芯片有 FIFO,可以稍微缓解溢出问题。 还有一种做法是调整波特率,如果不是必须的高波特率,降低速率可以减少溢出风险。 你试过用 HAL_UART_Receive_IT 吗?这个函数会自动处理 RXNE,但 ORE 还是需要自己手动清除。 有时候 flash 擦写造成的中断阻塞时间太长,甚至可以考虑用外部 SPI Flash 存储数据,避免 CPU 被占用。 这个坑让我想起了早期 51 单片机的串口溢出问题,STM32 也不能完全避免,还是得靠代码处理好异常情况。 当串口接收中断被更高优先级的中断打断,并且高优先级中断处理时间较长时,串口接收寄存器可能会在上次接收到的数据还没有被读走的情况下再次接收到新的数据。 连续溢出可能导致通信协议失效,影响系统功能。