声明
串口接收一段数据需要进入中断的次数太多了,为了充分利用CPU,使用空闲中断是更好的选择
步骤
一、CubeMX生成有关串口的配置
串口全局中断勾上、DMA和DMA的中断勾上
二、在main函数里使能两个串口的中断
第一个空闲中断、第二个接收寄存器不为空中断(后面解释这个和普通的串口接收中断有什么不同)
空闲中断经过实测,未进行串口传输虽然算是总线空闲,但是并不触发这个中断,并且数据发送完成也算是空闲,但是不触发。仅有数据接收完成总线空闲时才会触发。
三、具体实现
具体实现如下,利用数据到达产生的中断做起点来启动DMA,随后立马关掉该中断,不想让它和普通的接收中断一样
DMA一经启动就不由CPU管了,让它背后读数据,当空闲中断到来时就代表接收完毕了,此时的DMA也完成任务了,空闲中断内将DMA复位并处理数据然后再次使能:数据寄存器不为空中断。
起点是数据到达产生的中断,终点是总线空闲产生的中断,在空闲中断里再次让数据到达时产生中断,则形成了闭环,最重要的是只有起点和终点需要CPU运行中断函数,数据接收是由DMA实现的,这比普通的串口接收中断有着更少的中断次数。
四、 对比HAL_UARTEx_ReceiveToIdle
函数
HAL_UARTEx_ReceiveToIdle
函数的流程:
-
初始化检查:
检查huart
句柄是否有效,接收缓冲区pData
是否非空,以及接收大小Size
是否大于 0。 -
设置状态:
设置 UART 的接收状态为忙碌,并标记接收类型为HAL_UART_RECEPTION_TOIDLE
。 -
初始化接收计数器:
初始化huart->RxXferSize
和huart->RxXferCount
为接收的总数据量。 -
处理字长和奇偶校验:
根据 UART 初始化配置,确定接收数据是以 8 位还是 16 位宽度处理。 -
接收循环:
使用循环等待并接收数据,直到接收到所有数据或检测到空闲事件。 -
空闲事件检测:
如果在接收任何数据之前检测到空闲事件,函数将结束并返回HAL_OK
。 -
接收中断处理:
如果 UART 接收数据寄存器非空 (RXNE
事件),函数将从 UART 数据寄存器读取数据,并更新接收缓冲区和已接收数据长度。 -
超时管理:
如果设置了超时时间,函数将检查是否超时。如果超时,将返回HAL_TIMEOUT
。 -
正常结束:
一旦接收到所有数据,函数将更新已接收数据长度*RxLen
,并将 UART 接收状态设置为就绪。 -
错误处理:
如果 UART 接收状态不是就绪状态,函数将返回HAL_BUSY
。
HAL_UARTEx_ReceiveToIdle
函数并没有采用DMA,而此贴做法可以进入DMA释放CPU