STM32串口接收,接收一段时间后接收不到数据
问题和解决方法
最近项目在使用STM32L152串口和上位机高频收发数据。发现上位机给STM32高频发送数据时出现,开始STM32接收正常,一段时间后STM32接收不到数据。
根据 link 了解到可能接收过载(Overrun error)。如果出现过载和并开启RXNE中断,则会触发ORE中断。(本人开启了RXNE中断)
判断过载方法:连接你的单片机进入仿真,peripherals->system view->USART里选择你的当前可能宕机的串口号,则会出现该串口的寄存器,在新出现的页卡里找到ISR寄存器展开,往下翻找到ORE,看是否被打上了√,当发生串口过载错误时,就会出现此现象。
解决方法:查阅参考手册,如下说明,其实很简单。就是通过读取ORE中断标志位,并读取USART_DR寄存器。
解决代码示例如下:
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_ORE_RX) != RESET){
uint8_t receiveData = USART_ReceiveData(USART2);
}
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
uint8_t receiveData = USART_ReceiveData(USART2);
}
}
好了问题解决,但是为什么会出现过载呢?
先看下串口DR寄存器结构:
USART_DR寄存器其实是TDR和RDR寄存器组成成为的一个寄存器。给用户访问其实是一个寄存器地址,但是在STM32芯片内部是两个寄存器。怎么访问TDR和RDR取决于用户是读取还是写入USART_DR,因为发送寄存器TDR也只需要写入,接收寄存器RDR也只需要读取嘛。
然后具体看下RDR是怎么收到数据的,接收数据从RX来,首先来到接收移位寄存器,然后等用户取走RDR数据再转移到RDR寄存器,最后再由用户读取RDR。
知道了数据流向,再看参考手册中对过载的说明可知。
- 过载发生在RXNE被置位同时新的数据被接收,也就是说RDR中数据未被用户及时读取导致在移位寄存器中新来到的数据无法转移到RDR。
- 并且发生过载时,RDR中数据是不变的。而被重写的是移位寄存器,导致过载期间所有数据丢失。
- 看手册解释,使能RXNEIE,感觉ORE和RXNE必定同时发生,但是实际测试ORE和RXNE不一定同时发生,应该只取决于数据从移位寄存器转移至RDR瞬间的状态。
因此可以解释,出现过载为什么我读不到数据,这是由于出现过载没有及时取走RDR中数据和清ORE Flag。
STM32串口接收数据丢失问题
接着测试发现:STM32串口接收数据间断丢失几个byte
这与由于本人使用的中断太多,以及中断优先级分配问题导致。
综合考虑串口中断优先级,本人比较懒,直接将串口优先级设置位最高,可以解决该问题。不过还是建议综合考虑中断优先级分配。