C语言-回调函数的应用

什么是回调函数

回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C++、Python、ECMAScript等更现代的编程语言中还可以使用仿函数或匿名函数。

工作机制

  • ⑴定义一个回调函数;
  • ⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
  • ⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。

应用案例

(1)应用层:通过调用hal层的函数,将回调函数注册到hal层
(2)硬件hal层:通过异步调用这个callback函数,实现将数据上报到应用层
(3)应用层:根据硬件层上报的采集数据,实现业务逻辑判断和执行
在这里插入图片描述

函数类型分类

1.输入性函数( 异步调用的函数 )

输入型函数,我们称为响应式函数。比如说接收串口的数据。我们不知道数据什么时候来。
再比如:按键检测函数,我们不知道什么时候会按下按键,name就需要定义成响应式函数来实现

#include <stdio.h>

// 定义按键枚举类型
typedef enum {
    BUTTON_NONE,
    BUTTON_A,
    BUTTON_B,
    BUTTON_C
} Button;

// 定义按键事件处理器类型
typedef void (*ButtonEventHandler)(void);

// 按键事件处理函数:处理按键A事件
void handle_button_a() {
    printf("按下了按钮A,执行功能A\n");
}

// 按键事件处理函数:处理按键B事件
void handle_button_b() {
    printf("按下了按钮B,执行功能B\n");
}

// 按键事件处理函数:处理按键C事件
void handle_button_c() {
    printf("按下了按钮C,执行功能C\n");
}

// 模拟按键输入函数
Button get_button_input() {
    // 模拟获取按键输入
    return BUTTON_A; // 假设当前按下了按钮A
}

int main() {
    // 声明按键事件处理器数组,并初始化为相应的处理函数
    ButtonEventHandler event_handlers[] = {
        handle_button_a,
        handle_button_b,
        handle_button_c
    };

    // 获取按键输入
    Button button_pressed = get_button_input();

    // 根据按键输入选择相应的事件处理器并执行
    if (button_pressed >= BUTTON_A && button_pressed <= BUTTON_C) {
        // 获取事件处理器索引
        int index = button_pressed - 1;
        // 调用相应的事件处理器函数
        event_handlers[index]();
    } else {
        printf("无效的按键输入\n");
    }

    return 0;
}

#include <stdio.h>

// 定义温度回调函数的函数指针类型
typedef void (*TemperatureCallback)(float);

// 模拟温度传感器读取函数
float read_temperature_sensor() {
    // 模拟读取温度传感器数据
    return 25.5; // 返回模拟的温度值
}

// 温度回调函数:打印当前温度
void print_temperature(float temperature) {
    printf("当前温度为 %.2f 摄氏度\n", temperature);
}

// 温度回调函数:记录当前温度到日志文件
void log_temperature(float temperature) {
    FILE *log_file = fopen("temperature_log.txt", "a");
    if (log_file != NULL) {
        fprintf(log_file, "%.2f\n", temperature);
        fclose(log_file);
    } else {
        printf("无法打开日志文件\n");
    }
}

// 主函数:设置回调函数,并定期读取温度传感器数据调用回调函数
int main() {
    // 定义回调函数指针变量
    TemperatureCallback callback;

    // 设置回调函数为打印温度
    callback = print_temperature;

    // 定时读取温度传感器数据,并调用回调函数处理
    while (1) {
        // 模拟定时读取温度传感器数据
        float temperature = read_temperature_sensor();
        // 调用回调函数处理数据
        callback(temperature);
        // 等待一段时间再次读取温度数据
        delay(1000); // 假设延时函数 delay 表示等待1秒
    }

    return 0;
}

在Javascript中也有类似的回调机制

  • (函数A: greetUser作为参数传入另一个函数B:getUserInput,函数A在函数B的内部某个时间节点被触发调用,这就是Javascript的异步操作):
// 模拟异步操作:获取用户输入
function getUserInput(callback) {
    // 模拟延时,以模拟异步操作
    setTimeout(function() {
        var userInput = prompt("请输入您的名字:");
        callback(userInput); // 将用户输入作为参数传递给回调函数
    }, 1000); // 假设延时1秒
}

// 回调函数:处理用户输入
function greetUser(username) {
    if (username) {
        alert("你好," + username + "!");
    } else {
        alert("您没有输入名字。");
    }
}

// 调用 getUserInput 函数,并传入 greetUser 回调函数
getUserInput(greetUser);

2.输出型函数

大家不知道有没用过C语言的库函数,比如说sizeof() 获取数据长度的函数,memcpy()是内存拷贝函数,我们调用这个函数之后呢,就能完成相应的功能,还有我们基于单片机的一些程序函数,比如说控制LED状态,继电器状态等,LCD驱动等。那么我们称他们为输出型函数。
输出型函数使我们主导的角色,我们知道什么时候应该调用他。

3. 小结

所以通过两个类型的分析,我们知道,回调函数基本是用于输入型函数的处理,比如说串口数据的接收,那么数据就是输入到单片机里面的,按键检测,按键状态是输入到单片机的。

再比如说ADC值采集,ADC值也是输入到单片机莉的,那么他们输入的时间节点是未知的,这些就能够用回调函数来处理。

回调函数还有一个作用就是为了封装代码,比如说做芯片或者模组的厂家,我们拿典型的STM32举例,像外部中断,定时器,串口等中断函数都是属于回调函数。这种函数的目的是把采集到的数据传递给用户,或者说应用层。


所以回调函数的核心作用就是:
1、把数据从一个.c文件传递到另一个.C文件,而不是采用全局变量的方法
2、对于这种数据传递方式,回调函数更加便于代码的封装。

参考文章

C 语言回调函数详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值