开发环境为STM32CubeMX
+STM32CubeIDE
,使用NUCLEO-G070RB测试
- 开启串口的中断和DMA
- DMA模式设为Circle
- 程序中使用
HAL_UARTEx_ReceiveToIdle_DMA()
函数开启接收。
HAL_UARTEx_ReceiveToIdle_DMA()
会开启DMA半满、DMA全满、串口空闲中断,并回调到HAL_UARTEx_RxEventCallback()
函数。对于这个特性,我们使用循环DMA,在每次进入中断时找出新接收到的数据,并丢入队列,让另一个线程通过状态机处理收到的数据。具体地说,记录下上次中断时缓冲区的数据尾,作为本次接收到数据的开始;记录下上次缓冲区存在的数据的长度,与本次缓冲区存在的数据长度相减得到本次接收数据的长度。在规定了帧头帧尾等数据下,即使没有一次性接收到完整的一帧,状态机还是能正常解析数据。
比如对于一个长度为8byte的缓冲区,接收两次数据,第一次为"123456"
第二次为"7890"
,可发生以下4次中断。
在错误波特率下串口外设会收到错误进而导致串口卡死等问题。串口外设收到错误后会进入HAL_UART_ErrorCallback()
回调,我们需要在此重启串口,并将回调中的两个位置和长度变量给清零。