代码改变世界

关于stm32不断进入串口中断的问题

2016-10-12 12:44  小竹心语  阅读(8215)  评论(0编辑  收藏  举报

问题说明:比如说我串口中断函数执行时间是2s,在2s内再次发生串口中断,就会造成无法进入接收中断

void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
led_toggle();
delay_ms(1000);
delay_ms(1000);
}
}

具体现象就是串口发送数据给单片机,led灯不会闪烁,但是用示波器观察单片机的RX脚,每次触发都有信号,说明串口是有把信号给单片机的。

于是做了下面这样的测试

void USART2_IRQHandler(void)
{
   
        led_toggle();
        delay_ms(1000);
        delay_ms(1000);
    
}

当进入串口中断后在2s内再次通过串口给单片机发送数据,则led灯会一直闪烁(每隔2s)即使没有再给单片机发送数据,led灯也会一直闪烁,是什么原因造成单片机一直进入串口中断呢?

于是做了下面这样的测试

void USART2_IRQHandler(void)
{
    
    led_toggle();
    delay_ms(1000);
    delay_ms(1000);
    
    if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);
        UART_RxBuf[0] = USART_ReceiveData( USART2 ); 
    }
    if(USART_GetITStatus(USART2,USART_IT_ORE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_ORE);
        UART_RxBuf[0] = USART_ReceiveData( USART2 );  
    }
    
    
    if(USART_GetITStatus(USART2,USART_IT_PE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_PE);
    }
    
    if(USART_GetITStatus(USART2,USART_IT_TXE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_TXE);
    }
    
    if(USART_GetITStatus(USART2,USART_IT_TC) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_TC);
    }
    
    if(USART_GetITStatus(USART2,USART_IT_IDLE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_IDLE);
    }
    
    if(USART_GetITStatus(USART2,USART_IT_LBD) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_LBD);
    }
    
    
    if(USART_GetITStatus(USART2,USART_IT_CTS) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_CTS);
    }
    
    
    if(USART_GetITStatus(USART2,USART_IT_ERR) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_ERR);
    }
    
    
    if(USART_GetITStatus(USART2,USART_IT_NE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_NE);
    }
    
    if(USART_GetITStatus(USART2,USART_IT_FE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_FE);
    }
    
}

发现触发中断的条件一种都不满足,但还是一直进入中断,查资料后发现

stm32中文参考手册541业

ORE:过载错误 (Overrun error)
RXNE仍然是’1’的时候,当前被接收在移位寄存器中的数据,需要传送至RDR寄存器时,硬
件将该位置位。如果USART_CR1中的RXNEIE’1’的话,则产生中断。由软件序列将其清零
(先读USART_SR,然后读USART_CR)
0:没有过载错误;
1:检测到过载错误。
注意:该位被置位时, RDR寄存器中的值不会丢失,但是移位寄存器中的数据会被覆盖。如果
设置了EIE位,在多缓冲器通信模式下, ORE标志置位会产生中断的

 

解决方法,在串口初始化配置时,打开ORE溢出中断

 USART_Init(USART2, &USART_InitStructure); //初始化串口4
    USART_ClearFlag(USART2, USART_FLAG_RXNE);//防止配置完就进入中断
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_ITConfig(USART2, USART_IT_ORE, ENABLE);//开启串口溢出中断
    USART_Cmd(USART2, ENABLE);                 
void USART2_IRQHandler(void)
{
    
    led_toggle();
    delay_ms(1000);
    delay_ms(1000);
    
    if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);
        UART_RxBuf[0] = USART_ReceiveData( USART2 ); 
    }
    if(USART_GetITStatus(USART2,USART_IT_ORE) != RESET)
    {
        USART_ClearITPendingBit(USART2,USART_IT_ORE);
        UART_RxBuf[0] = USART_ReceiveData( USART2 );  //这步一定要有的,相当于清空缓存区
    }
}