STM32——串口溢出ORE的前世今生

当数据接收区或者FIFO区有数据或者满时,又有新数据进来,会导致发生溢出错误,一旦发生溢出错误,RX 移位寄存区虽然能有新数据不断的覆盖,但是数据不会到达RXR或FIFO(现象是:RXNE在ORE置位时不会被置位),导致程序中不能读到新的数据。只有通过ICR清除ORE才能使得RXNE在接收到新数据时置位。

串口框图

溢出错误属于串口接收

USART receiver

溢出错误发生的原因

1、FIFO mode disabled
An overrun error occurs if a character is received and RXNE has not been reset.
Data can not be transferred from the shift register to the RDR register until the RXNE
bit is cleared.
The RXNE flag is set after every byte reception.
An overrun error occurs if RXNE flag is set when the next data is received or the previous DMA request has not been serviced.
2、FIFO mode enabled
An overrun error occurs when the shift register is ready to be transferred and the receive FIFO is full.
Data can not be transferred from the shift register to the USART_RDR register until there is one free location in the RXFIFO. The RXFNE flag is set when the RXFIFO is not empty.

An overrun error occurs if the RXFIFO is full and the shift register is ready to be transferred.

溢出错误后果

– the ORE bit is set;
– the RDR content will not be lost. The previous data is available by reading the USART_RDR register.
– The first entry in the RXFIFO will not be lost. It is available by reading the USART_RDR register.
the shift register will be overwritten. After that, any data received during overrun is lost.
– An interrupt is generated if either the RXFNEIE or EIE bit is set.
 

清除溢出错误

The ORE bit is reset by setting the ORECF bit in the USART_ICR register.
Note: The ORE bit, when set, indicates that at least 1 data has been lost.

When the FIFO mode is disabled, there are two possibilities
• if RXNE=’1’, then the last valid data is stored in the receive register (RDR) and can be read,
• if RXNE=’0’, the last valid data has already been read and there is nothing left to be read in the RDR register. This case can occur when the last valid data is read in the RDR register at the same time as the new (and lost) data is received.

寄存器 ISR Bit 3 ORE: Overrun error

This bit is set by hardware when the data currently being received in the shift register is ready to be transferred into the USART_RDR register while RXNE=’1’ (RXFF = ’1’ in case FIFO mode is enabled).

It is cleared by a software, writing ’1’ to the ORECF, in the USART_ICR register.

An interrupt is generated if RXNEIE/ RXFNEIE=’1’ or EIE = ’1’ in the USART_CR1 register.
0: No overrun error
1: Overrun error is detected

1、When this bit is set, the USART_RDR register content is not lost but the shift register is overwritten.
2、An interrupt is generated if the ORE flag is set during multi buffer communication if the EIEbit is set.
3、This bit is permanently forced to 0 (no overrun detection) when the bit OVRDIS is set in the USART_CR3 register

————————————————
版权声明:本文为CSDN博主「我是稻草人dcr」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012564117/article/details/94152663

在使用一个串口发数据的传感器过程中,发现程序第一次进入串口中断之后不再执行主函数的内容,中断中的内容也不执行。查询大量资料后发现:串口在接收数据过多时,会出现串口溢出错误,并进入溢出中断(ORE中断)。接下来是错误产生原因以及解决方法。 
(1)什么是ORE中断?为什么会产生? 

产生原因如上所述。

ORE标志位在USART_SR寄存器,但值得注意的是,当我们打开串口接收中断时,同时也就打开了ORE中断。

(2)如何解决? 
看了上面的资料之后,我知道程序是死在了串口溢出中断。处理中断时,我首先想到的是清除这个中断标志位,但是遇到了很多麻烦。

清除ORE位的方法:顺序执行对USART_SR和USART_DR寄存器的读操作。 
注意:在此使用USART_ClearITPendingBit(USART1, USART_IT_ORE);清除ORE位是没有任何作用的。 
还有ORE中断只能使用USART_GetFlagStatus(USART1, USART_FLAG_ORE) 读到(没有使能USART_IT_ERR中断时) 
这些都是在这个帖子里读到的http://blog.csdn.net/love_maomao/article/details/8234039帖子还指出了手册的翻译错误,哈哈,很厉害的博主(在此表白)。 
最后附上解决方案: 
中断服务函数:

if(USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET) 

USART_ClearFlag(USART2, USART_FLAG_ORE); //清除溢出中断 
}

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) 

USART_ClearITPendingBit(USART2, USART_IT_RXNE); 
//rebuf[num++] = USART_ReceiveData(USART2); 读取串口数据 
}
————————————————
版权声明:本文为CSDN博主「今天也迟到」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34401994/article/details/76359581

首先,要把串口配置成RXNE中断,具体的配置步骤可以参考我的文章《关于CubeMX的串口全双工接收发送锁死的问题》。

然后,使能RXNE中断和ORE中断,main.c中的代码如下:

void main(void)
{
    ...
    if(HAL_UART_Receive_IT(&huart2,(u8 *)&i,1) != HAL_OK)   Error_Handler();
    /* 开启接收错误中断 */
    __HAL_UART_ENABLE_IT(&huart2, UART_IT_ERR);
    ...
}

接着,在usart.c中加入串口错误中断回调函数的定义:

/* 中断错误处理函数,在此处理overrun错误 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    uint8_t i = 0;

    if(__HAL_UART_GET_FLAG(huart,UART_FLAG_ORE) != RESET) 
    {
        __HAL_UART_CLEAR_OREFLAG(huart);
        HAL_UART_Receive_IT(huart,(u8 *)&i,1);
    }
}

单纯处理溢出中断的话,这样就可以了;如果想处理其他一些错误,比如帧错误等等,就继续判断标志位;如果想在检测到错误之后做一些处理,也可以写在回调函数里。

最后还想说几点,在之前的程序中,溢出中断也与死机如影随行,如果出现了溢出中断就意味着百分百丢失了数据。而我们能做的处理无非就是清除标志位防止中断反复触发,从而使整个系统能继续运行下去。至于丢失的数据,已经不可能找回来了。

溢出中断只是作为一种防备手段来预防极小概率发生的情况,我当时用了3套串口,其中一个几乎满负荷运行,另一个用于接收GPS数据的低优先级串口使用了溢出中断,最后本来一秒一次的GPS数据在校验之后一分钟才能更新一次,甚至需要更长时间,最后还是不得不使用了串口空闲中断,为此需要为接收GPS数据保留一个1k的ram作缓存区。希望之后能找到更好的处理办法。。。
————————————————
版权声明:本文为CSDN博主「mickey35」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mickey35/article/details/78529637

发布了24 篇原创文章 · 获赞 46 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/m0_37777700/article/details/103885541