在使用STM32HAL库的串口时,注意到有两种发送、接收函数,分别是HAL_UART_Transmit、HAL_UART_Transmit_IT和HAL_UART_Receive、HAL_UART_Receive_IT。
其描述都提及了blocking mode和non blocking mode,两种模式。经过查找,我在串口HAL库的.c文件的顶部使用说明中发现了如下一段描述:
这两段说明了两种模式的区别,翻译如下:
阻塞模式:以轮询模式进行接收,直到接收到预期的数据数量,或者直到IDLE事件发生。接收只在函数执行期间处理。
当函数退出时,不可能发生数据接收。HAL状态和实际接收的数据元素数量,在完成传输后由函数返回。
非阻塞模式:接收使用中断或DMA执行。
这些API返回HAL状态。
当使用中断模式时,数据处理的结束将通过专用的UART IRQ指示;当使用DMA模式时,数据处理的结束将通过DMA IRQ指示。
HAL_UARTEx_RxEventCallback()用户回调将在接收过程中执行
当检测到接收错误时,将执行HAL_UART_ErrorCallback()用户回调。
总结
似乎这两种模式只对接收模式有效,在阻塞模式下,函数会在两种情况下结束:1、接收到设置的数据量;2、时间超出设定的时间(单位是ms,原理参考UART_WaitOnFlagUntilTimeout函数)。根据最后一句话“HAL状态和实际接收的数据元素数量,在完成传输后由函数返回”,我查看了函数的返回值类型HAL_StatusTypeDef,其定义如下图:
可见,返回值只反映了状态,并没有反映实际接收的数量,于是我又查看了函数内部,发现实际接收数量被串口处理结构体所接收,实际接收的结构体成员为RxXferCount。
而非阻塞模式就是中断了,需要注意的一点是HAL_UART_Receive_IT只是开启中断,当在中断处理函数中处理完成之后还需要重复调用这个函数来持续开启中断,否则数据只会被接收一次。