在单片机编程中,最主要的是掌握单片机工作的时间节拍,最大限度地利用CPU资源,下面提供一种基于基准定时器进行软件定时、任务执行采用分时复用的方法,规定每个任务执行的时间,执行时间到后切换下一任务。
u16 Timer_Count = 0,Timer_Count_OverFlow = 0;
u16 this_time = 0,last_time = 0,time_overflow = 0;
#define Timer_Period 60000
#define OutofRunningTime(time) (Timer_Period*Timer_Count_OverFlow+this_time-last_time >= time)
#define TIME_MS(x) (1*x)
#define TIME_S(x) (1000*x)
#define TOTAL_TASK 3 //定义任务总数
enum {TASK1,TASK2,TASK3};
void 26 interrupt PIT0(void) //中断定时器,1ms进入一次
{
Timer_Count ++;
if(Timer_Count >= Timer_Period)
{
Timer_Count = 0;
Timer_Count_OverFlow ++;
}
}
static u8 task1(void)
{
last_time = Timer_Count;
Timer_Count_OverFlow = 0;
for(;;)
{
this_time = Timer_Count;
do_some_thing();
if(OutofRunningTime(TIME_S(2)))
return TASK2;
}
}
static u8 task2(void)
{
last_time = Timer_Count;
Timer_Count_OverFlow = 0;
for(;;)
{
this_time = Timer_Count;
do_some_thing();
if(OutofRunningTime(TIME_S(2)))
return TASK3;
}
}
static u8 task3(void)
{
last_time = Timer_Count;
Timer_Count_OverFlow = 0;
for(;;)
{
this_time = Timer_Count;
do_some_thing();
if(OutofRunningTime(TIME_S(2)))
return TASK1;
}
}
u8 task_process(u8 task)
{
u8 next_task;
switch(task)
{
case TASK1:
next_task = task1();
break;
case TASK2:
next_task = task2();
break;
case TASK3:
next_task = task3();
break;
default:
break;
}
return next_task;
}
u8 Current_Task = TASK1;
void main(void)
{
Current_Task = system_init();
for(;;)
{
Current_Task = task_process(Current_Task);
}
}
代码中定义了一个时基为1ms的中断定时器,用Timer_Count作为自由计数值,计数上限为Timer_Period,到达上限后将Timer_Count清零,同时统计一次溢出次数Timer_Count_OverFlow,溢出次数自由计数,直到溢出后清零,进入下一轮回。 main函数执行的时候进入task_process函数,同时传递进入当前需要执行的任务号,首次执行的时候传递进去的任务号是TASK1,从task1()开始执行,下面对task1()进行分析。
执行任务函数的时候先记录当前Timer_Count的值,将溢出次数Timer_Count_OverFlow清零,然后一直执行for循环中的do_some_thing(),同时记录和检测当前Timer_Count的值,根据当前Timer_Count值和进入任务时的Timer_Count比较,如果时间到达我们需要任务执行的时间,则跳出for循环,同时返回下次要执行的任务号,在main函数中根据返回的任务号进入下一任务的执行。
代码中实现的是基本的软件架构,并没有具体程序执行的功能代码,移植的时候只要使用单片机中的一个定时器,不断产生1ms的定时中断即可。
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』