一、相同点
省流一句话勉强都可以称作为回调函数。从HAL的片内外设驱动(如xx_hal_xxx.c)这一层的函数(如UART_Receive_IT、HAL_UART_Init)发起调用HAL_UART_MspInit(huart)、huart->MspInitCallback(huart)、UART_InitCallbacksToDefault、void (* MspInitCallback)(struct __UART_HandleTypeDef *huart); HAL_UART_RxCpltCallback(huart)、huart->RxCpltCallback(huart)。
// 启用回调注册API
HAL_StatusTypeDef HAL_UART_RegisterCallback( \
UART_HandleTypeDef *huart, \
HAL_UART_CallbackIDTypeDef CallbackID, \
void (*pCallback)(UART_HandleTypeDef *huart))
{
HAL_StatusTypeDef status = HAL_OK;
if(CallbackID = HAL_UART_RX_COMPLETE_CB_ID)
{
huart->RxCpltCallback = pCallback; // 动态注册回调
}
return status;
}
1. 如果是使用注册回调机制,在用户自定义的重定义的强定义的回调函数定义好后,那么还需要再通过HAL_UART_RegisterCallback这个注册回调函数去把用户自定义的重定义的强定义的回调函数的函数指针去赋值给huart句柄(也是一个指向结构体的指针)中的函数指针类型的成员。见上图。虽然注册回调函数(如HAL_UART_RegisterCallback)在(如xx_hal_xxx.c)等HIL片内外设驱动层定义,注册回调函数(如HAL_UART_RegisterCallback)在(如xx_hal_xxx.h)等HIL片内外设驱动层声明,但是用户使用注册回调函数(带实参的,如HAL_UART_RegisterCallback)一般就不要在(如xx_hal_xxx.c)等HIL片内外设驱动层调用注册回调函数了。而是与用户自定义的重定义的强定义的回调函数一样,在用户的main.c等用Application层中调用注册回调函数注册回调函数(带实参的,如HAL_UART_RegisterCallback)。
2. 如果是传统的弱定义回调机制,则直接由HIL片内外设驱动层(如xx_hal_xxx.c)中的驱动函数调用由用户自定义的重定义的强定义的回调函数(传统的弱定义回调函数被其覆盖掉)。但是由用户自定义的重定义的强定义的回调函数也一般是在用户的main.c等用Application层中重定义的。
总结:为啥都可以称为回调函数,那是因为底层的HAL库只提供了个功能实现的半成品,最后需要由用户或者cubmx高层去完成全部功能。HIL库去调用用户编写的函数,而不是正常用户调用HIL的函数,倒反天罡,说句回调函数也不冤枉。
二、不同点
HAL_XXX_MspInit是在基本上都是在CubMx层由CubMx图形化配置实现的初始化程序,主要与时钟控制和GPIO这些底层硬件相关的Msp,很少需要用户去在用户层码代码去实现程序的。而HAL_XXX_XxxCallback都是需要用户去在用户层码代码去实现程序的。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/woshihonghonga/article/details/148486662
|
|