时刻片轮询法,在许多书本中有说到,并且有许多时分都是与操作体系一同呈现,也便是说许多时分是操作体系中运用了这一办法。不过咱们这儿要说的这个时刻片轮询法并不是挂在操作体系下,而是在前后台程序中运用此法。也是本贴要详细阐明和介绍的办法。
关于时刻片轮询法,虽然有不少书本都有介绍,但大多说得并不体系,仅仅提提概念罢了。下面自己将详细介绍自己形式,并参阅他人的代码树立的一个时刻片轮询架构程序的办法,我想将给初学者有必定的学习性。
记住在前不久自己发帖《1个守时器多处复用的问题》,因为时刻的问题,并没有详细阐明怎样完结1个守时器多处复用。在这儿咱们先介绍一下守时器的复用功用。
运用1个守时器,可所以恣意的守时器,这儿不做特别阐明,下面假定有3个使命,那么咱们应该做如下作业:
1. 初始化守时器,这儿假定守时器的守时中止为1ms(当然你能够改成10ms,这个和操作体系相同,中止过于频频功率就低,中止太长,实时性差)。
2. 界说一个数值:
仿制内容到剪贴板
代码:
#define TASK_NUM(3)//这儿界说的使命数为3,表明有三个使命会运用此守时器守时。
uint16 TaskCount[TASK_NUM];//这儿为三个使命界说三个变量来寄存守时值
uint8TaskMark[TASK_NUM];//相同对应三个标志位,为0表明时刻没到,为1表明守时时刻到。
3. 在守时器中止服务函数中增加:
仿制内容到剪贴板
代码:
void TImerInterrupt(void)
{
uint8 i;
for (i=0; i
{
if (TaskCount[i])
{
TaskCount[i]–;
if (TaskCount[i] == 0)
{
TaskMark[i] = 0x01;
}
}
}
}
代码解说:守时中止服务函数,在中止中逐一判别,假如守时值为0了,表明没有运用此守时器或此守时器现已完结守时,不着处理。不然守时器减一,知道为零时,相应标志位值1,表明此使命的守时值到了。
4. 在咱们的使用程序中,在需求的使用守时的当地增加如下代码,下面就以使命1为例:
仿制内容到剪贴板
代码:
TaskCount[0] = 20;// 延时20ms
TaskMark[0]= 0x00;// 发动此使命的守时器
到此咱们只需求在使命中判别TaskMark[0]是否为0x01即可。其他使命增加相同,至此一个守时器的复用问题就完结了。用需求的朋友能够试试,作用不错哦。。。。。。。。。。。
经过上面临1个守时器的复用咱们能够看出,在等候一个守时的到来的一起咱们能够循环判别标志位,一起也能够去履行其他函数。
循环判别标志位:
那么咱们能够想想,假如循环判别标志位,是不是就和上面介绍的次序履行程序是相同的呢?一个大循环,仅仅这个延时比一般的for循环准确一些,能够完结准确延时。
履行其他函数:
那么假如咱们在一个函数延时的时分去履行其他函数,充分使用CPU时刻,是不是和操作体系有些相似了呢?可是操作体系的使命办理和切换是十分复杂的。下面咱们就将使用此办法架构一向新的使用程序。
时刻片轮询法的架构:
1.规划一个结构体:
代码:
//使命结构
typedefstruct_TASK_COMPONENTS
{
uint8Run;//程序运转符号:0-不运转,1运转
uint8TImer;//计时器
uint8ItvTIme;//使命运转间隔时刻
void(*TaskHook)(void);//要运转的使命函数
}TASK_COMPONENTS;//使命界说
这个结构体的规划十分重要,一个用4个参数,注释说的十分详细,这儿不在描绘。
2. 使命运转标志出来,此函数就相当于中止服务函数,需求在守时器的中止服务函数中调用此函数,这儿独立出来,并于移植和了解。
代码:
voidTaskRemarks(void)
{
uint8i;
for(i=0;i//逐一使命时刻处理
{
if(TaskComps[i].TImer)//时刻不为0
{
TaskComps[i].Timer–;//减去一个节拍
if(TaskComps[i].Timer==0)//时刻减完了
{
TaskComps[i].Timer=TaskComps[i].ItvTime;//康复计时器值,重新下一次
TaskComps[i].Run=1;//使命能够运转
}
}
}
}
咱们仔细比照一下次函数,和上面守时复用的函数是不是相同的呢?
3. 使命处理
代码:
voidTaskProcess(void)
{
uint8i;
for(i=0;i//逐一使命时刻处理
{
if(TaskComps[i].Run)//时刻不为0
{
TaskComps[i].TaskHook();//运转使命
TaskComps[i].Run=0;//标志清0
}
}
}
此函数便是判别什么时分该履行那一个使命了,完结使命的办理操作,使用者只需求在main()函数中调用此函数就能够了,并不需求去别离调用和处理使命函数。
到此,一个时刻片轮询使用程序的架构就建好了,咱们看看是不是十分简略呢?此架构只需求两个函数,一个结构体,为了使用方面下面将再树立一个枚举型变量。
下面我就就说说怎样使用吧,假定咱们有三个使命:时钟显现,按键扫描,和作业状况显现。
1. 界说一个上面界说的那种结构体变量
代码:
staticTASK_COMPONENTSTaskComps[]=
{
{0,60,60,TaskDisplayClock},//显现时钟
{0,20,20,TaskKeySan},//按键扫描
{0,30,30,TaskDispStatus},//显现作业状况
//这儿增加你的使命。。。。
};
在界说变量时,咱们现已初始化了值,这些值的初始化,十分重要,跟详细的履行时刻优先级等都有联系,这个需求自己把握。
来历;21ic