细究STM32 HAL库的中断式串口接收

细究STM32 HAL库的中断式串口接收,第1张

当使用HAL库中断式串口接收,除了在NVIC中使能全部串口中断,我们还需要使用 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) 来使能串口接收中断。

函数请求UART句柄 huart ,接收数据缓存区 pData ,以及期望接收的数据个数 size 。

进入到该函数中,首先会确保huart处于空闲状态,否则返回 HAL_BUSY ,同时校验参数 pData 和 size 的合法性,视情况返回 HAL_ERROR

随后使用宏 __HAL_LOCK() 锁死huart,这样huart在释放前被调用时,返回 HAL_BUSY

后面是关于接收模式,接收超时中断的一些设置,并不重要,在程序最后return时调用了 UART_Start_Receive_IT(huart, pData, Size) ,进入下一层,该函数是整个中断注册的关键。

进入 UART_Start_Receive_IT(),首先是把接收数据缓存区以及接收个数传递给句柄huart, 清除掉接收中断服务函数指针 ,以及进行一些必要的设置。

随后会根据USART的设置来选择不同的中断服务函数

得到4个中断函数,我们研究相对简单的8倍过采样RxISR

在接收ISR中,配置好Mask后,如果UART有数据,则会读 RDR 数据接收寄存器,反之直接清掉 RXNE 标记位.

重点在于后面的判断语句,这也是整个HAL库中断式串口接收的阴间之处

在确定读取到预期数量的数据后,会直接 失能RXNE串口接收中断 ,同时 也清理RxISR函数指针 ,回调 接收事件函数 HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize) 接收完毕函数 HAL_UART_RxCpltCallback(huart)

那么这个RxISR是在哪里被调用的呢?答案在 void USART1_IRQHandler(void) 中的 HAL_UART_IRQHandler() 中

使用空闲中断。HAL库中,从中断到回调函数运行了不少的程序,频繁的中断或会造成数据溢出,为了避免这个问题,使用指定接收一定长度的数据,再调用回调函数,这可以接收大数据,但是这种情况则造成了,要求每次的包是固定长度,为了解决以上一些问题,网上最常用的办法是使用空闲中断,即在串口空闲的时候,触发一次中断,通知内核,本次运输完成了。串口空闲中断的判定是:当串口开始接收数据后,检测到1字节数据的时间内没有数据发送,则认为串口空闲了。由于内核在串口接收数据到空闲这段时间,是不受理串口数据的,所以还需要使用DMA来协助把数据传送到指定的地方,当数据传输完成后,通知内核去处理。

HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)函数的功能是设置接收中断的参数,以及使能接收中断。查看一下它的代码就明白了。

函数的第一个参数是串口实例句柄,第二个参数是用于存储接收数据的指针,第三个则是接收多少个数据之后调用接收完成回调函数HAL_UART_RxCpltCallbac


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11543378.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存