szt1993 发表于 2025-4-24 23:10

51单片机的回调函数+定时中断


​ 使用回调函数有个有点,就是可以在高一层定义回调,高一层不用调用低一层的代码,低一层直接调用高一层的回调来掉自己这一层的函数。

​ 我们使用回调函数就是把我们想调用的函数套一层壳子,下面总结下这层壳子要怎么封装和之前写的定时器中断整合在一起。

在定时器的驱动头文件中定义函数指针的类型;

typedef void(*Timer0_Callback)(void);
在定时器驱动C文件中定义函数指针的数组,用来注册函数;

static Timer0_Callback s_timer0_callbacks;
在初始化定时器中将函数指针的数组置空;

// 初始化时函数指针的数组置空
for (i = 0; i < MAX_CALLBACK_COUNT; i++){
   s_timer0_callbacks = NULL;
}
写注册函数的函数,供外部调用

u8 Dri_Timer0_RegisterCallback(Timer0_Callback callback) {
    u8 i;
    for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
      // 注册过,返回
      if (s_timer0_callbacks == callback)return 1;
    }

    // 没注册过,注册
    for (i = 0; i < MAX_CALLBACK_COUNT; i++) {
      if (s_timer0_callbacks == NULL) {
            s_timer0_callbacks = 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) s_timer0_callbacks();
    }
}
使用时,初始化定时器,调用注册回调函数将我们想实现的逻辑放进去就行了

// 代码略
定时器中断可以用来解决之前的延时问题,使用起来很灵活,可根据实际情况操作,可以代替延时函数实现按键消抖、数码管的计数等,通过回调函数可以对定时器中断作优化,也很灵活,需要多多练习。

页: [1]
查看完整版本: 51单片机的回调函数+定时中断