在HAL库中,串口使用中断接收需进行错误处理,下面介绍应如何正确处理。
环境:Windows10 、STM32CubeIDE 1.17.0
芯片:STM32F407VETX
HAL库版本:STM32Cube_FW_F4_V1.28.1
HAL库的中断处理函数中有着这样的描述:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
...
...
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
consider error as blocking */
/* Blocking error : transfer is aborted
Set the UART state ready to be able to start again the process,
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
...
...
}
从这段可以发现,HAL库想让我们在遇到串口过载,与启用DMA发生串口错误时重新开始串口接收。
在不使用DMA仅使用中断接收的情况下,只需要在遇到过载错误时重新开始中断接收,其他的错误甚至可以忽略。
但是在启动DMA时,任何错误都需要重新开始DMA接收,在错误回调中不用区分错误类型,一律重新接收。
在HAL库中串口错误回调有两种用法:
1、默认的方式,所有串口共用一个回调函数。在下面的例子中使用串口1开启空闲中断接收,在这种形况下只需处理过载即可。
/*Call legacy weak error callback*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
//Example:
HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
if (huart->ErrorCode == HAL_UART_ERROR_ORE)
{
HAL_UARTEx_ReceiveToIdle_IT(&huart1, Rxmsg, sizeof(Rxmsg));
}
return;
}
}
2、对于需要单独处理的串口可以注册专用的回调函数。
查看HAL库中的错误回调调用方式:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
...
...
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
...
...
}
不难发现这个回调函数需要我们自行注册,并且需要启用宏。
HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart,
HAL_UART_CallbackIDTypeDef CallbackID,
pUART_CallbackTypeDef pCallback);
使用CubeMX很方便的启用宏:
在启用宏后注册相应的错误处理函数即可:
//在stm32f4xx_hal_conf.h中手动配置
#define USE_HAL_USART_REGISTER_CALLBACKS 1U /* USART register callback enabled */
//定义回调函数。在使用DMA的情况下,所有错误都需要重新开始接收
void UART1_ErrorCallback(UART_HandleTypeDef *huart)
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, Rxmsg, sizeof(Rxmsg));
}
//注册回调函数
HAL_UART_RegisterCallback(&huart1,HAL_UART_ERROR_CB_ID,UART1_ErrorCallback);