17. 嵌入式开发中的回调函数:解耦与灵活编程的利器

回调函数的基本概念

回调函数是一种通过函数指针实现的编程机制,允许将函数作为参数传递或在运行时动态指定逻辑。本质上,它是一种"函数调用函数"的模式,常用于解耦底层驱动与上层应用逻辑。

实现中断回调函数的步骤

定义函数指针类型

使用 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;

回调函数的核心价值

解耦与扩展性

  • 底层驱动无需修改即可适配不同业务逻辑。
  • 业务代码独立于硬件层,便于维护和复用。

典型应用场景

  1. 外设驱动(如UART接收完成回调):
c 复制代码
typedef void (*UART_RxCpltCallback)(uint8_t *data, uint16_t len);
UART_RxCpltCallback uartRxCb;

void USART_IRQHandler(void) {
    if (/*接收完成*/) {
        uartRxCb(rxBuffer, rxLen); // 触发数据回调
    }
}
  1. RTOS任务通知

    通过回调处理定时器超时或消息队列事件,避免任务与内核强耦合。

  2. 传感器数据上报

    传感器驱动采集数据后,通过回调将结果传递给应用层。

实际工程建议

参数化回调设计

为增强灵活性,可定义带参数的函数指针类型:

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;
};

通过上述方法,回调函数能显著提升嵌入式代码的模块化程度和可维护性。