使用回调函数有个有点,就是可以在高一层定义回调,高一层不用调用低一层的代码,低一层直接调用高一层的回调来掉自己这一层的函数。
我们使用回调函数就是把我们想调用的函数套一层壳子,下面总结下这层壳子要怎么封装和之前写的定时器中断整合在一起。
在定时器的驱动头文件中定义函数指针的类型;
typedef void(*Timer0_Callback)(void);
在定时器驱动C文件中定义函数指针的数组,用来注册函数;
static Timer0_Callback s_timer0_callbacks[MAX_CALLBACK_COUNT];
在初始化定时器中将函数指针的数组置空;
// 初始化时函数指针的数组置空
for (i = 0; i < MAX_CALLBACK_COUNT; i++){
s_timer0_callbacks[i] = NULL;
}
写注册函数的函数,供外部调用
u8 Dri_Timer0_RegisterCallback(Timer0_Callback callback) {
u8 i;
for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
// 注册过,返回
if (s_timer0_callbacks[i] == callback) return 1;
}
// 没注册过,注册
for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
if (s_timer0_callbacks[i] == NULL) {
s_timer0_callbacks[i] = callback;
return 1;
}
}
return 0;
}
通过定时器执行注册过的函数
void Dri_Timer0_Func() interrupt 1 {
u8 i;
// 更新计数器中的数,保证下次还是1ms后触发
TL0 = T1MS; // 这个T1MS是宏定义,(65536 - 11059200 / 12 / 1000)
TH0 = T1MS >> 8;
// 调用所有的回调函数
for(i = 0; i<MAX_CALLBACK_COUNT; i++){
if (s_timer0_callbacks[i]) s_timer0_callbacks[i]();
}
}
使用时,初始化定时器,调用注册回调函数将我们想实现的逻辑放进去就行了
// 代码略
定时器中断可以用来解决之前的延时问题,使用起来很灵活,可根据实际情况操作,可以代替延时函数实现按键消抖、数码管的计数等,通过回调函数可以对定时器中断作优化,也很灵活,需要多多练习。
|