4.3.Callback函数
类似于MSP函数,个人认为Callback函数主要帮助用户应用层的代码编写。
还是以USART为例,在标准库中,串口中断了以后,我们要先在中断中判断是否是接收中断,然后读出数据,顺便清除中断标志位,然后再是对数据的处理,这样如果我们在一个中断函数中写这么多代码,就会显得很混乱:
<p>void USART3_IRQHandler(void) <span style="white-space:pre"> </span>//串口1中断服务程序</p><p>{</p><p><span style="white-space:pre"> </span>u8 Res;</p><p><span style="white-space:pre"> </span>if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)</p><p><span style="white-space:pre"> </span>{</p><p><span style="white-space:pre"> </span>Res =USART_ReceiveData(USART3);<span style="white-space:pre"> </span>//读取接收到的数据</p><p><span style="white-space:pre"> </span>/*数据处理区*/</p><p><span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> </p><p> } </p><p>} </p>
而在HAL库中,进入串口中断后,直接由HAL库中断函数进行托管:
<p>void USART1_IRQHandler(void) <span style="white-space:pre"> </span></p><p>{ </p><p><span style="white-space:pre"> </span>HAL_UART_IRQHandler(&UART1_Handler);<span style="white-space:pre"> </span>//调用HAL库中断处理公用函数</p><p><span style="white-space:pre"> </span>/***************省略无关代码****************/<span style="white-space:pre"> </span></p><p>}</p>
HAL_UART_IRQHandler这个函数完成了判断是哪个中断(接收?发送?或者其他?),然后读出数据,保存至缓存区,顺便清除中断标志位等等操作。
比如我提前设置了,串口每接收五个字节,我就要对这五个字节进行处理。
在一开始我定义了一个串口接收缓存区:
<p>/*HAL库使用的串口接收缓冲,处理逻辑由HAL库控制,接收完这个数组就会调用HAL_UART_RxCpltCallback进行处理这个数组*/</p><p>/*RXBUFFERSIZE=5*/</p><p>u8 aRxBuffer[RXBUFFERSIZE];</p>
在初始化中,我在句柄里设置好了缓存区的地址,缓存大小(五个字节)
<p>/*该代码在HAL_UART_Receive_IT函数中,初始化时会引用*/</p><p><span style="white-space:pre"> </span>huart->pRxBuffPtr = pData;//aRxBuffer</p><p> huart->RxXferSize = Size;//RXBUFFERSIZE</p><p> huart->RxXferCount = Size;//RXBUFFERSIZE</p>
则在接收数据中,每接收完五个字节,HAL_UART_IRQHandler才会执行一次Callback函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
在这个Callback回调函数中,我们只需要对这接收到的五个字节(保存在aRxBuffer[]中)进行处理就好了,完全不用再去手动清除标志位等操作。
所以说Callback函数是一个应用层代码的函数,我们在一开始只设置句柄里面的各个参数,然后就等着HAL库把自己安排好的代码送到手中就可以了~
综上,就是HAL库的三个与标准库不同的地方之个人见解。
个人觉得从这三个小点就可以看出HAL库的可移植性之强大,并且用户可以完全不去理会底层各个寄存器的操作,代码也更有逻辑性。但与此带来的是复杂的代码量,极慢的编译速度,略微低下的效率。看怎么取舍了。
|