最近在中断收发的原理与使用中还是模糊,本文主要是对中断收发的阶段性学习成果予以陈述。
之前我看的是江协写的文档,但是那边的函数实现有些怪:
|
|
它的主要问题在于还是使用阻塞式发送 HAL_UART_Transmit()
而且用了一个很奇怪的 Serial_getRxFlag()
并且这个函数在主循环中一直被调用,不太符合中断调用的目的。使用一个 Flag 太奇怪了。
此外,我在整个 main 中想要将发送也采用中断但最后走向失败。
中断式接收
中断式接收关键在于自己实现 HAL_UART_RxCpltCallback()
。因为原本的该函数是没东西的。
|
|
该函数是接收完成后触发的回调函数。我们的实现如下:
|
|
也就是在接收后检查 UART 句柄确认后就通过中断发送到串口。
使用 HAL_UART_Transmit_IT
需要 HAL_UART_TxCpltCallback()
这这里用于在发送完成后重启中断接收
|
|
实际我们在 main()
函数内放置的只有以下函数
|
|
这个可以启动串口接收,同时在接收到指定大小的数据时触发中断。需要注意的是这里是一次性中断,在中断后不会重新打开中断也就是接收不到新的数据了。
在这两个回调函数中都有对 huart->Instance
进行判断,这边需要做些补充说明:
这里的 Instance
存储的是 UART 寄存器的基地址具体还需要更多深入的对 UART 研究才能更好的理解。
其实这边几乎等价于江协的 huart == &huart1
以上代码基本上可以实现串口发送接收使用中断来完成了。
HAL_UART_RxCpltCallback()
和 HAL_UART_TxCpltCallback()
这两个都是回调函数,用于在串口接收/发送完成后由系统或库进行调用。也就是说,在每次接收/发送完成后,不需要我们在主循环中调用,系统就会自动调用这个函数完成一些东西。而且,这个函数是需要我们自己去实现的。也就是说我们通过自己的实现来告诉 stm32 在接收/发送完成后需要做些什么。
在最初主函数内通过 HAL_UART_Receive_IT
函数启动串口接收,并在最后触发中断调用
HAL_UART_RxCpltCallback
回调函数。
比如说,我们要在串口接收到信息后就发送回信息,那么上文的 HAL_UART_RxCpltCallback()
就能做到这一点。只是在接收完成后调用 HAL_UART_Transmit_IT(&huart1, &ByteRecv, 1);
发送字节。上文我们提到 HAL_UART_Receive_IT
的中断是一次性的。所以我们还需要在发送完成后重新打开中断,也就是说,我们要在 **
HAL_UART_TxCpltCallback** 中重新执行
HAL_UART_Receive_IT`