既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
大家好,我是无际。
今天继续来聊下回调函数。
之前写过一篇受到了广大老铁们的认可。
最近有几个新学员被回调函数搞得有点懵逼。
不理解为什么要搞这种绕来绕去、指针指来指去的函数。
先写篇文章预热一下,晚上再直播跟大家互动讲解和答疑。
其实并不是我想把简单的东西复杂化,而是如果你想写出好的代码架构,回调函数是必不可少的。
如果你去看那些大神写的程序,你会发现他们都是这样做的,比如说蓝牙协议栈、实时操作系统、STM32固件库等等。
每个人写得风格可能不一样,但是本质是一样的。
我们先来理解一下回调函数的作用。
函数我一般喜欢分为输出型和输入型(个人理解)。
输出型:
就是我们主动去调用的控制函数,比如说控制LED灯去亮和灭,控制蜂鸣器响和不响,控制LCD显示,控制继电器吸合和断开。
简单来说,就是我们知道什么时候该去调用这些函数,比如说满足某些条件的时候,我们就会主动去调用这些函数。
这种函数,就是输出型函数。
输入型:
输入型函数一般是用在不同.c文件/不同层(硬件层、应用层)之间传递信号和数据的,比如说按键检测、串口数据。
我们不知道什么时候按键会被按下、什么时候串口会有数据过来对吧?
当然,我们可以写一个带返回值的函数,然后定时去检测,比如说定时10ms去扫描一下按键。
Unsigned char ScanKey()
{undefined
//按键检测程序…
}
然后我们在主程序用:
while(1)
{undefined
Unsigned char key;
If(10ms时间到)
{undefined
Key = ScanKey();
}
if(Key == 有效按键值)
{undefined
//执行按键功能程序
}
}
这样不断地去扫描按键,检测按键是否被按下。
这种方式当然也是可以的,只是不够专业,不够好。
因为这个我需要一直在while循环里判断Key的值,然后根据Key的值来判断有没有按键按下,在一定程度上,造成了cpu资源的浪费。
而且有些应用场景,这种方式不好实现,比如说串口数据,你不能一直在while循环里判断是否有新的串口数据过来吧?
那我们理想的一种状态是什么?
就是如果有按键按下了,或者有新的数据来了,再通知我。
这种通知方式一般叫事件触发,就是触发了按键这个事件,我才去处理。
所以,这个时候回调函数就能很好地解决这种需求。
我们还是拿按键来举例。
前面我说每个人写回调函数的风格可能都不一样,STM32固件库的那些中断处理函数基本都是回调函数,但是跟我的编写风格还是有些差异。
我们在写回调函数的时候,需要以下几步:
第一步:
自定义一个函数指针类型,类型名称是KeyEvent_CallBack_t。
typedef void (*KeyEvent_CallBack_t)(KEY_VALUE_TYPEDEF keys);
还有这个一般是要自定义在头文件,因为别的.c文件也会用到。
这是一个无返回值的,形参是KEY_VALUE_TYPEDEF枚举类型的函数指针类型。
一般这个形参keys就是我们最终要通过回调函数传递到别的.c文件的信号/数据,如果是按键检测的话也就是按键值,是哪个按键按下的。
我们来看下KEY_VALUE_TYPEDEF这个枚举都有哪些值?
typedef enum
{undefined
KEY_IDLE_VAL,
KEY1_CLICK,
KEY1_CLICK_RELEASE,
KEY1_LONG_PRESS,
KEY1_LONG_PRESS_CONTINUOUS,
KEY1_LONG_PRESS_RELEASE, //5
KEY2_CLICK, //6
KEY2_CLICK_RELEASE,
KEY2_LONG_PRESS,
KEY2_LONG_PRESS_CONTINUOUS,
KEY2_LONG_PRESS_RELEASE,
KEY3_CLICK, //11
KEY3_CLICK_RELEASE,
KEY3_LONG_PRESS,
KEY3_LONG_PRESS_CONTINUOUS,
KEY3_LONG_PRESS_RELEASE,
KEY4_CLICK, //16
KEY4_CLICK_RELEASE,
KEY4_LONG_PRESS,
KEY4_LONG_PRESS_CONTINUOUS,
KEY4_LONG_PRESS_RELEASE,
KEY5_CLICK, //21
KEY5_CLICK_RELEASE,
KEY5_LONG_PRESS,
KEY5_LONG_PRESS_CONTINUOUS,
KEY5_LONG_PRESS_RELEASE,
KEY6_CLICK, //26
KEY6_CLICK_RELEASE,
KEY6_LONG_PRESS,
KEY6_LONG_PRESS_CONTINUOUS,
KEY6_LONG_PRESS_RELEASE,
}KEY_VALUE_TYPEDEF;
我们这个项目总共有6个按键,每个按键需要检测短按、短按释放、长按、长按释放、连续长按这5个功能,所以总共有30个不同的枚举值分别来对应不同按键的不同功能。
第二步:
自定义了函数指针类型以后,我们就可以通过KeyEvent_CallBack_t这个类型名称,去定义我们的函数指针变量。
KeyEvent_CallBack_t KeyScanCBS;
那KeyScanCBS就是函数指针,所以它的返回值是void类型,形参是KEY_VALUE_TYPEDEF枚举类型的。
最终就是把这个指针指向别的.c文件的函数,从而实现不同.c文件之间的数据传递,同时又能保持很好的可移植性(相互独立,互不干扰)。
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-QdeXVO7k-1715801344765)]
[外链图片转存中…(img-z0vzEUbM-1715801344765)]
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!