C语言实现一个简单的多定时任务功能模块
一.简介
在项目开发中,很多功能模块都会用到定时功能,比如说定时3分钟后点亮一个led灯,定时1个小时后自动关机等,如果项目中只用到了一个应用层级别的定时功能,可能简单的写一下就好了,但是当项目中有多个定时功能需求的话,反而是把定时功能单独拿出来,写成一个功能模块,更简单更清晰。
二.功能实现
创建TimSet.c,TimSet.h,在TimSet.h文件中声明需要用的数据类型,及声明外部文件调用要用的api函数,在TimSet.c中实现api接口函数
2.1在头文件中定义数据类型
//枚举用到定时功能的模块,根据自己需求定义
typedef enum
{TSM_HEAT,//加热定时功能TSM_SAFE,//安全工作时间定时功能//...NUM_TSM
}EM_TIMSETMOUDLE;//枚举定时功能的不同状态
typedef enum
{TIMSETSTA_STOP,TIMSETSTA_PASUSE,TIMSETSTA_RUN,TIMSETSTA_END
}EM_TIMSETSTA;//定义触发定时到达处理函数时的触发方式
#define TSHTYPE_TIMOVER 1 //到达设定时间后触发处理函数
#define TSHTYPE_INTERRUPT 2 //未到达设定时间,中间人为打断//定义函数指针类型
typedef void (*pFun)(uint8_t);//定义处理结构体
typedef struct
{ pFun handleFun; //定义定时到达后的处理函数EM_TIMSETSTA curSta;EM_TIMSETSTA lastSta; unsigned long clkTarget; //秒定时计数unsigned long tarTime; //预计定时时间unsigned long timeCnt; //定时计数器
}ST_TIMSETDATA;
2.2在头文件中声明api接口函数
//初始化指定功能模块,指定其处理函数
void TimSet_InitOne(EM_TIMSETMOUDLE tarMoudle,pFun handleFun);//总初始化函数
void TimSet_InitAll(void);//启动某个具体模块定时功能
void TimSet_Start(EM_TIMSETMOUDLE tarMoudle,unsigned long seconds);//停止某个具体模块定时功能,原有计时时间清零
void TimSet_Stop(EM_TIMSETMOUDLE tarMoudlee);//暂停某个具体模块定时功能,再次调用TimSet_Start()开启运行,原有定时时间不清零
void TimSet_Pause(EM_TIMSETMOUDLE tarMoudle);//外部主动结束一个定时任务,同TimSet_Stop()不同的是会触发处理函数
void TimSet_ExStopMoudle(EM_TIMSETMOUDLE tarMoudle);//轮循处理函数,每一个时间单位调用一次,当前时间单位为1s
void TimSet_Loop(void);//获取某个定时任务的定时总时间
unsigned long TimSet_GetTargetTime(EM_TIMSETMOUDLE tarMoudle);//获取某个定时任务的定时剩余时间
unsigned long TimSet_GetLeftTime(EM_TIMSETMOUDLE tarMoudle);//获取某个定时任务的状态
EM_TIMSETSTA TimSet_GetMoudleSta(EM_TIMSETMOUDLE tarMoudle);//获取总共的定时任务数量
unsigned char TimSet_GetMaxTask();//获取当前处于运行状态的定时任务数量
unsigned char TimSet_GetRunTask();
2.3在源文件中定义全局变量
#include "TimSet.h"ST_TIMSETDATA gs_TimSetData[NUM_TSM]; static unsigned char gu8_CurRunTask=0; //当前处于运行状态的定时任务数量
2.4在源文件中实现api接口函数
//具体某个定时功能模块定时完成或中间打断后调用的处理函数示例
void TimSet_HeatHandle(uint8_t type)
{if(type==TSHTYPE_INTERRUPT){}else if(type==TSHTYPE_TIMOVER){}else{}}//具体某个定时功能模块定时完成或中间打断后调用的处理函数示例
void TimSet_SafeHandle(uint8_t type)
{if(type==TSHTYPE_INTERRUPT){}else if(type==TSHTYPE_TIMOVER){}else{}
}//初始化一个定时功能模块
void TimSet_InitOne(EM_TIMSETMOUDLE tarMoudle,pFun handleFun)
{ if(tarMoudle>=NUM_TSM){return;}gs_TimSetData[tarMoudle].handleFun = handleFun;gs_TimSetData[tarMoudle].lastSta = TIMSETSTA_END;gs_TimSetData[tarMoudle].curSta = TIMSETSTA_STOP;gs_TimSetData[tarMoudle].tarTime = 0;gs_TimSetData[tarMoudle].timeCnt = 0;
}//定时模块总初始化函数
void TimSet_InitAll()
{TimSet_InitOne(TSM_HEAT,TimSet_HeatHandle);TimSet_InitOne(TSM_SAFE,TimSet_SafeHandle);//....}//启动,单位S
void TimSet_Start(EM_TIMSETMOUDLE tarMoudle,unsigned long seconds)
{if(tarMoudle>=NUM_TSM){return;}if(gs_TimSetData[tarMoudle].curSta != TIMSETSTA_RUN){gu8_CurRunTask++;}gs_TimSetData[tarMoudle].tarTime = seconds;if (gs_TimSetData[tarMoudle].curSta != TIMSETSTA_PASUSE){gs_TimSetData[tarMoudle].timeCnt = 0;}gs_TimSetData[tarMoudle].curSta = TIMSETSTA_RUN;
}//停止对应的模块的定时
void TimSet_Stop(EM_TIMSETMOUDLE tarMoudle)
{if(tarMoudle>=NUM_TSM){return;}if(gs_TimSetData[tarMoudle].curSta != TIMSETSTA_STOP){gu8_CurRunTask--;}gs_TimSetData[tarMoudle].curSta = TIMSETSTA_STOP;
}//暂停定时,再次调用启动函数时不会将原有计时数清零
void TimSet_Pause(EM_TIMSETMOUDLE tarMoudle)
{if(tarMoudle>=NUM_TSM){return;}if(gs_TimSetData[tarMoudle].curSta != TIMSETSTA_PASUSE){gu8_CurRunTask--;}gs_TimSetData[tarMoudle].curSta = TIMSETSTA_PASUSE;
}//获取某个定时模块的目标定时时间
unsigned long TimSet_GetTargetTime(EM_TIMSETMOUDLE tarMoudle)
{if(tarMoudle>=NUM_TSM){return;}return gs_TimSetData[tarMoudle].tarTime;
}//获取某个定时模块的定时剩余时间
unsigned long TimSet_GetLeftTime(EM_TIMSETMOUDLE tarMoudle)
{if(tarMoudle>=NUM_TSM){return;}if (gs_TimSetData[tarMoudle].timeCnt >= gs_TimSetData[tarMoudle].tarTime){return 0;}else if (gs_TimSetData[tarMoudle].curSta == TIMSETSTA_STOP){return 0;}return gs_TimSetData[tarMoudle].tarTime - gs_TimSetData[tarMoudle].timeCnt;
}//获取某个定时模块的状态
EM_TIMSETSTA TimSet_GetMoudleSta(EM_TIMSETMOUDLE tarMoudle)
{return gs_TimSetData[tarMoudle].curSta;
}//获取总定时任务
unsigned char TimSet_GetMaxTask()
{return NUM_TSM;
}//获取当前处于运行状态的定时任务
unsigned char TimSet_GetRunTask()
{return gu8_CurRunTask;
}//外部主动结束一个定时任务,同TimSet_Stop()不同的是会触发处理函数
void TimSet_ExStopMoudle(EM_TIMSETMOUDLE tarMoudle)
{gs_TimSetData[tarMoudle].handleFun(TSHTYPE_INTERRUPT);TimSet_Stop(tarMoudle);
}//一个单位时间调用一次,当前为1s
void TimSet_Loop()
{uint8_t index=0;for(index = 0; index < NUM_TSM; ++index){switch (gs_TimSetData[index].curSta){case TIMSETSTA_STOP:gs_TimSetData[index].lastSta = gs_TimSetData[index].curSta; break;case TIMSETSTA_RUN:gs_TimSetData[index].lastSta = gs_TimSetData[index].curSta; gs_TimSetData[index].timeCnt++;if (gs_TimSetData[index].timeCnt >= gs_TimSetData[index].tarTime){gs_TimSetData[index].handleFun(TSHTYPE_TIMOVER);gs_TimSetData[index].curSta = TIMSETSTA_STOP;gs_TimSetData[index].timeCnt = 0;} break;case TIMSETSTA_PASUSE:gs_TimSetData[index].lastSta = gs_TimSetData[index].curSta; break;default:gs_TimSetData[index].curSta = TIMSETSTA_STOP;break;} }
}
说明:
1.在TimSet_InitAll()函数中实现所有用到的功能模块的定时任务的初始化,将处理函数与定时模块绑定。
2.调用TimSet_Start()函数启动一个定时任务,调用TimSet_Stop()结束一个定时任务,调用TimSet_Pause()暂停一个定时任务
3.调用TimSet_Pause()暂停一个定时任务后,再次启动时调用TimSet_Start()启动,之前的计时时间不会清零
4.一个定时任务启动后,如果在定时期间遇到某些情况需要提前取消定时任务,如需调用对应的处理函数处理这一情况,就调用TimSet_ExStopMoudle()函数结束此任务,如不需调用对应的处理函数,调用TimSet_Stop()即可。
5.一个时间单位调用一次TimSet_Loop()函数,一个任务的定时时间=时间单位*设定的定时数值。当前我用的时间单位为1s,所以1s调用一次TimSet_Loop()即可
三.其它
有任何bug可以留言提出来,随时修改修复。
如果想交流各种遇到的问题,可以加qq群869630744,一起交流一起进步
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!