回调函数的基本概念
回调函数是一种通过函数指针实现的编程机制,允许将函数作为参数传递或在运行时动态指定逻辑。本质上,它是一种"函数调用函数"的模式,常用于解耦底层驱动与上层应用逻辑。
实现中断回调函数的步骤
定义函数指针类型
使用 typedef 声明一个无参数、无返回值的函数指针类型:
c
typedef void (*call_back_t)(void);
声明全局函数指针变量
定义一个全局变量存储回调函数地址:
c
call_back_t funCallBackPtr;
在中断服务函数中调用回调
在定时器中断服务函数中通过指针间接调用注册的回调函数:
c
void TIM_IRQHandler(void) {
if (funCallBackPtr != NULL) {
funCallBackPtr(); // 触发回调
}
}
实现具体功能函数
编写实际业务逻辑的函数(如打印日志):
c
void logPrint(void) {
printf("定时器中断触发,当前时间:%d\n", getSystemTime());
}
注册回调函数
将业务函数地址赋值给函数指针:
c
funCallBackPtr = logPrint;
回调函数的核心价值
解耦与扩展性
- 底层驱动无需修改即可适配不同业务逻辑。
- 业务代码独立于硬件层,便于维护和复用。
典型应用场景
- 外设驱动(如UART接收完成回调):
c
typedef void (*UART_RxCpltCallback)(uint8_t *data, uint16_t len);
UART_RxCpltCallback uartRxCb;
void USART_IRQHandler(void) {
if (/*接收完成*/) {
uartRxCb(rxBuffer, rxLen); // 触发数据回调
}
}
-
RTOS任务通知
通过回调处理定时器超时或消息队列事件,避免任务与内核强耦合。
-
传感器数据上报
传感器驱动采集数据后,通过回调将结果传递给应用层。
实际工程建议
参数化回调设计
为增强灵活性,可定义带参数的函数指针类型:
c
typedef void (*event_callback_t)(void *context, uint32_t event_id);
空指针检查
调用回调前需验证指针有效性,防止未注册时触发异常:
c
if (callback != NULL) {
callback(arg1, arg2);
}
多回调管理
复杂场景可使用回调数组或链表支持多个监听器:
c
struct CallbackNode {
event_callback_t func;
void *context;
struct CallbackNode *next;
};
通过上述方法,回调函数能显著提升嵌入式代码的模块化程度和可维护性。