第八集 定时器周期性调度任务
本集所讲述的周期性调度任务也就是每隔一定时间需要执行的任务,要实现该类任务基本思路是使用定时器,每隔一定的时间产生中断,在中断服务函数中对计时变量进行自增,在主函数的死循环中对该计时变量进行判断,当计时变量达到一定的值之后,执行任务,并将计时变量清除。
官方对这种周期性调度的任务进行了封装,我来介绍一下大体思路
对于周期性任务无非就两个要素:一个是周期是多少,另一个是执行的具体任务,对应程序中的某个功能函数,官方定义了一个任务组件的结构体
typedef struct
{
u8 Run; //任务状态:Run/Stop
u16 TIMCount; //定时计数器
u16 TRITime; //重载计数器
void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;
变量Run表示时间到了任务应该执行还是时间没到不应该执行
TIMCount为定时器中断中的计数器,用来看定时的时间有没有到
TRITime为重载计数器,在TIMCount清零后给其赋值让其重新开始计时
void (*TaskHook) (void)是一个函数指针,用以指定定时时间到后所执行的任务
官方定义了一个上述结构体的数组Task_Comps,用以存储一系列的周期性任务,我们来看看这些任务是如何调度的
官方定义了两个函数,一个用在中断服务函数中处理计时变量,另一个用在主函数中进行任务调度
首先看第一个函数
void Task_Marks_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps[i].TIMCount) /* If the time is not 0 */
{
Task_Comps[i].TIMCount--; /* Time counter decrement */
if(Task_Comps[i].TIMCount == 0) /* If time arrives */
{
/*Resume the timer value and try again */
Task_Comps[i].TIMCount = Task_Comps[i].TRITime;
Task_Comps[i].Run = 1; /* The task can be run */
}
}
}
}
外层的for循环用以遍历每个任务,我认为外部的if判读多余,如果不是在数组初始化时给TIMCount赋值0,程序执行过程中它被减为0后马上重载了,内部的话就是一个定时器中断后计数器减一,减到0了重载计数器的值,同时让任务执行标志位置一。
第二个函数是主函数的任务调度
void Task_Pro_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps[i].Run) /* If task can be run */
{
Task_Comps[i].Run = 0; /* Flag clear 0 */
Task_Comps[i].TaskHook(); /* Run task */
}
}
}
同样外层的for循环用以遍历每个任务,然后检查任务执行标志位,如果标志位被置一就执行任务,并且将标志位清0,说明任务执行过了。
官方提供的模板可以说非常简洁,便于理解,非常不错。