有时候我们在进行一些操作的时候需要周期性的完成一些操作,操作一定时间或者操作几次后关闭,为了避免在主函数加入延时而影响系统的实时性,这里给出一种简易的软件定时器实现方案
typedef struct{
int soft_tim;//用于软件定时器计时
unsigned char tim_init;
}Tim;
首先是定时器初始化的俩结构体,赋值就在实例化的时候进行,免得在写一个Init函数了 例如这样初始化
Tim tim1={0,0};//定义一个定时器
然后就是几个要用到的函数
#define __WEAK __attribute__((weak))
__weak void soft_Tim_callback(void){//用户调用
}
void soft_Tim_open(Tim * tim){//打开定时器
tim->tim_init=1;
}
void soft_Tim_close(Tim * tim){//关闭定时器
tim->tim_init=0;
}
//简易软件定时器回调 num为多少秒回调一次,时基为1ms tim为为实例化的定时器对象
//该函数放在1ms一次的硬件定时器中
void soft_Tim_init(int num,Tim *tim){
if(tim->tim_init){
tim->soft_tim++;
if(tim->soft_tim==num){
tim->soft_tim=0;
soft_Tim_callback();
}
}
}
我是将soft_Tim_init放在硬件定时器的1ms中断中的,来提供时基,用户调用的soft_Tim_callback是一个弱定义函数,由用户重新定义。使用时将soft_Tim_init一个硬件定时器里面提供时基,然后soft_Tim_open打开定时器,把需要实现的功能放在soft_Tim_callback中就能定时调用了,开几个软件定时器就这么干几次。
2023-8-11 补充
据我长期使用的体验来说,之前上面的使用体验有点繁琐,因此所有我最新一套的软件定时器方案。全部代码如下
首先是.h
#ifndef _TIMER_H
#define _TIMER_H
typedef struct{
unsigned int soft_tim;//用于软件定时器计时
unsigned char tim_init; //打开和关闭定时器
unsigned int soft_tim_threshold; //定时器触发阈值
void (*callback)(void); //触发的回调函数
}Tim;
void soft_Tim_open(Tim * tim);
void soft_Tim_close(Tim * tim);
void soft_Tim_clean(Tim * tim);
void soft_Tim_heartbeat(Tim *tim);
void soft_Tim_init(int num,Tim *tim,void (*callback)(void));
#endif
然后是.c
#include "timer.h"
void soft_Tim_open(Tim * tim){//打开定时器
tim->tim_init=1;
}
void soft_Tim_close(Tim * tim){//关闭定时器
tim->tim_init=0;
}
void soft_Tim_clean(Tim * tim){//清除定时器计数
tim->soft_tim=0;
}
//简易软件定时器回调 num为多少秒回调一次,时基为1ms tim为为实例化的定时器对象
//num触发阈值
void soft_Tim_heartbeat(Tim *tim){
if(tim->tim_init){
tim->soft_tim++;
if(tim->soft_tim>=tim->soft_tim_threshold){
tim->soft_tim=0;
tim->callback();
}
}
}
//初始化定时器
void soft_Tim_init(int num,Tim *tim,void (*callback)(void)){
tim->callback=callback;
tim->soft_tim=0;
tim->soft_tim_threshold=num;
tim->tim_init=1;
}
使用方法如下:
/*首先定义一个软件定时器*/
Tim tim1;
/*然后定义一个该定时器定时到达之后自动调用的回调函数*/
void tim1_callback(void){
//do some thing
}
/*然后进行初始化并打开*/
soft_Tim_init(1000,&tim1,tim1_callback);
/*最后把定时器心跳放入硬件定时器提供时基*/
soft_Tim_heartbeat(&tim1);
完成以上操作当定时器达到之后就会自动触发相应的回调函数,注意不要在回调函数中放耗时的操作,要快进快出。