单片机开发中运用到的回调函数的用法:
首先把程序分为两个层:硬件层程序,应用层程序;
硬件层程序:比如led,按键,adc等硬件的配置,硬件的功能把它们归为硬件层的程序;
应用层程序:比如main.c的各类函数如main函数里的业务逻辑的实现,把它们归为应用层程序;
为何使用回调函数?
避免使用全局变量标志实现硬件层的数据读取。比如,在硬件层中,串口收到数据,那么应用层如何获取到硬件层收到的数据?简单的实现是,在串口接收到数据后,利用全局变量标志,把它置1。在应用层这边轮询访问该全局变量,一旦检测到该标志位为1,那么就在缓冲区中读取数据出来。(这样的方式可以实现应用层从硬件层获取数据,但是这样的方式不利于后续程序的移植)。
回调函数方便函数的封装。
什么时候用回调函数?
在这里,首先我们可以把函数调用分为两种类型,输出类的函数,输入类的函数。
其中输出类函数指的是,我们主动调用该函数会输出对应的值。比如sizeof()函数、memcpy()函数、控制led灯的亮灭等。
输入类的函数也为响应式的函数。比方我们接收串口的数据,不知道数据什么时候来,数据是输入到单片机里面的;按键检测的函数,我们不知道什么时候会按下按键,按键的状态也是输入到单片机里面的;再比方ADC值的采集,ADC的值也是输入到单片机里的。
因此输入类函数的输入数据的时间结点都是未知的,这时候就能够用回调函数进行处理。
回调函数的用法
在硬件层中,自定义函数指针类型,形参为传递给应用层的数据;
在硬件层中,定义该类型的变量,并且定义一个函数指针注册函数;
在软件层中,定义一个函数(句柄)形参和返回值与上面自定义的函数一致;
调用函数指针函数,形参为函数名。通过硬件的功能函数,实现软件层对硬件层的数据读取;
回调函数的具体用法和图示
首先在硬件层程序中(.h),自定义函数指针类型,形参为需要传给应用层的数据;

在硬件层程序中(.c),定义该自定义类型的函数指针变量;

在硬件层程序中,定义一个函数指针注册函数,相当于一个对外的接口;

在应用层程序中,定义一个函数,该函数的形参和返回值与函数指针类型一致;

最后在主函数调用函数指针注册函数,把定义好的函数名作为形参传入,通过硬件层的功能函数,实现应用层对硬件层数据的读取。

最后运行结果如下:

总结

如上图所示,通过回调函数的使用。在主函数中,很清晰看到函数的封装度好,函数的调用简便;
方便后续做代码的移植(应用层和硬件层相互独立),只需要提供对外的函数指针注册函数就能实现对硬件层的数据读取;