HAL库中对串口中断执行流程的分解

电子说

1.2w人已加入

描述

我们使用轮询方式接收计算机端发送过来的数据,但是这种方式需要一直在循环语句中查询是否有数据发送过来,这种方式效率非常低。

为了提高处理器的执行效率,我们使用中断方式接收计算机端发送过来的数据,当计算机端有数据发送过来时,会触发STM32的串口中断,并执行中断回调函数。

在这种方式中,不用反复去查询串口是否接收到数据,所以效率非常高,实时性也更好。

HAL库的中断接收函数和中断发送函数分别为HAL_UART_Receive_IT和HAL_UART_Transmit_IT。下面我们对常用的中断方式接收函数HAL_UART_Receive_IT进行重点介绍。

HAL_UART_Receive_IT函数的原型如下

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

它的三个参数分别为串口句柄,接收到的数据存储的目标地址和接收多少个字节的数据。

打开函数HAL_UART_Receive_IT,可以看到它的定义如图8-24所示。

STM32

图8-24 函数HAL_UART_Receive_IT内容示意图

可以看到,函数HAL_UART_Receive_IT并没有实际进行数据接收,而只是对串口句柄huart的接收信息进行初始化和使能相关中断,这些使能中断的最后一个即为使能串口接收中断。

由于函数HAL_UART_Receive_IT本质上是对串口的中断进行使能,所以和设置系统时钟一起放置于main函数的系统初始化代码中,而不是放在while循环中反复查询、执行。

为了便于对比,图8-25给出了轮询方式接收函数的定义。

STM32

图8-25 轮询方式接收函数HAL_UART_Receive定义示意图

由轮询方式接收函数的定义可以看到,函数HAL_UART_Receive是确实在接收数据并保存到参数pData指向的存储单元中。这点和中断方式接收函数完全不同,读者千万不要被函数名迷惑了。

那中断方式是如何接收数据的呢?下面我们来介绍中断方式接收数据的步骤。

(1)使能接收中断。

(2)接收到数据后触发接收数据中断,此时程序按以下步骤执行。

①到中断向量表中找到USART1的中断入口,如图8-26所示。

STM32

图8-26 USART1中断函数入口

②执行中断函数USART1_IRQHandler,在该中断函数中调用HAL库的USART1中断函数,如图8-27所示。

STM32

图8-27 USART的中断函数的内容

注意,该函数需要用户自己实现,如果用户使用CubeMX生成工程,则工程会自动在输出文件stm32f4xx_it.c中生成该函数。

③执行HAL库的中断函数HAL_UART_IRQHandler。在该函数中先判断是否存在接收错误,如果不存在,则执行函数UART_Receive_IT(),如图8-28所示。

STM32

图8-28 函数HAL_UART_IRQHandler定义示意图

④执行接收完成中断函数UART_Receive_IT(),如图8-29所示。

STM32

图8-29 函数UART_Receive_IT()定义示意图

由图可见,在该函数中首先判断字长是9位还是8位,如果是8位,则根据是否使能奇偶校验使用如下语句读取数据(见图8-29中的①):

if (huart- >Init.Parity == UART_PARITY_NONE)  /* 如果没有使能奇偶校验,数据位为8位 */


     {


        *huart- >pRxBuffPtr++ = (uint8_t)(huart- >Instance- >DR & (uint8_t)0x00FF);


     }


     else  /* 如果使能了奇偶校验,数据位为7位 */


     {


       *huart- >pRxBuffPtr++ = (uint8_t)(huart- >Instance- >DR & (uint8_t)0x007F);


     }

在上述程序段中,程序首先将接收到的数据保存到句柄huart的接收区缓冲指针pRxBuffPtr指向的存储单元中,然后指针pRxBuffPtr的值加1,指向下一个存储单元。

所以,在中断方式接收中,数据的接收在中断函数中完成。

读到一个数据后,huart的接收计数变量RxXferCount的值减1,并判断减到0了没有,如果减到0了,说明数据已经接收完成,关闭串口中断,如图8-30中的②所示,接着执行接收完成中断回调函数HAL_UART_RxCpltCallback,如图8-30中的③所示。

⑤执行回调函数HAL_UART_RxCpltCallback。由于在步骤④中执行函数UART_Receive_IT时已经关闭了串口的接收中断,所以如果要继续采用中断方式接收数据,则需要在回调函数中再次调用函数HAL_UART_Receive_IT使能串口中断。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分