问题描述:
在频繁对板子掉电上电的测试中发现偶尔会使串口无法进入接收回调函数,但却能进入串口接收中断,通过查询huart结构体的errcode发现它等于HAL_UART_ERROR_ORE,HAL库的注释为overrun eroor过载错误,这个过载错误通过查询资料发现是因为串口波特率过高导致MCU处理不过来发生的,但是我9600的波特率应该不至于因为数据过多导致串口过载吧。
直接上结论,因为我板子是作为从机,主机一直在给我发数据,正常情况下是不会出现问题的,但是如果数据在我打开接收中断之前就来的话,就会导致MCU无法进入接收回调函数(具体原因我猜测是硬件软件还没准备好接收但是总线上就有数据了,硬件是会一直接收的,但是软件又没有来得及处理数据导致缓冲区满了)
//如果在这之前总线上有数据到来就会出现overrun故障
HAL_UART_Receive_IT(&huart1, buf, 1);
接下来通过示波器直观的观察一下出现overrun的情景
黄线:打开接收中断后将电平置0
蓝线:MCU串口接收引脚
上电时不会出现overrun的情况:
上电时会出现overrun的情况:
从上图可以看出MCU在打开接收中断之前串口总线上就有数据要接收了,这种情况就会出现串口过载故障,如果我们不进行故障标志位清除的话,串口就会卡死,一直无法进入接收回调函数
又因为CUBEMX在我们配置串口时默认使能了Overrun检测
虽然使能了Overrun检测,但是如果出了Overrun故障却没有处理措施,需要我们自己定义EorrCallback函数
解决办法:定义ErrorCallback函数将ORE故障标志位清除,重新打开接收中断
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart->EroorCode & HAL_UART_ERROR_ORE)
{
__HAL_UART_CLEAR_OREFLAG(huart);
huart->RxState = HAL_UART_STATE_READY; //让串口重新回到就绪状态
huart->Lock = HAL_UNLOCKED;
HAL_UART_Receive_IT(&huart1, buf, 1); //重新打开接收中断
}
}
网上还有一种说法就是在配置串口时直接disable Overrun检测也可以解决