本帖最后由 老陆693 于 2018-5-6 16:59 编辑
给楼主推荐一本书:《时间触发嵌入式系统设计模式》//定义一个结构
typedef struct
{
void (*pTask)(void); //函数指针
unsigned int sDelay; //休眠时间
unsigned int sPeriod; //休眠时标
unsigned char sRunMe; //运行时
}sTask;
sTask SCH_tasks_G[SCH_MAX_TASKS];
unsigned char Error_code_G;
//使用单片机一个定时器做为Systemtick,这段代码放在定里器中断里面
定时器中断函数(void)
{
unsigned char uc_taskPoll;
//调试器任务查询
for(uc_taskPoll=0; uc_taskPoll<SCH_MAX_TASKS; ++uc_taskPoll)
{
if(SCH_tasks_G[uc_taskPoll].pTask) //任务有分配
{
if(SCH_tasks_G[uc_taskPoll].sDelay == 0) //有任务要开始
{
SCH_tasks_G[uc_taskPoll].sRunMe += 1;
if(SCH_tasks_G[uc_taskPoll].sPeriod)
SCH_tasks_G[uc_taskPoll].sDelay = SCH_tasks_G[uc_taskPoll].sPeriod;
}
else
SCH_tasks_G[uc_taskPoll].sDelay -= 1;
}
}
}
//任务调度
void SCH_Disptch_Tasks(void)
{
unsigned char Index;
while(1){
for(Index=0; Index<SCH_MAX_TASKS; ++Index)
{
if(SCH_tasks_G[Index].sRunMe > 0)
{
(*SCH_tasks_G[Index].pTask)(); //执行任务
SCH_tasks_G[Index].sRunMe -= 1; //清除任务需要执行的标志
if(SCH_tasks_G[Index].sPeriod == 0) //如果这是个“单次”任务,将它从队列中删除
SCH_Delete_Task(Index);
}
//空闲任务
// SCH_Report_Status(); //报告系统状况
// SCH_Go_To_Sleep(); //进入体眠
}
}
//添加任务
//Delay:第一次运行延时,为0立即执行,以后执行按PERIOD循环时间
//单次任务将PERIOD设置为0
unsigned char SCH_Add_Task(void (* pFunction)(),
unsigned int Delay,
unsigned int PERIOD)
{
unsigned char Index = 0;
while((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS)) //找一个任务空隙放置任务
++ Index;
if(Index == SCH_MAX_TASKS) //任务列队已满
{
Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
return SCH_MAX_TASKS;
}
SCH_tasks_G[Index].pTask = pFunction;
SCH_tasks_G[Index].sDelay = Delay;
SCH_tasks_G[Index].sPeriod = PERIOD;
SCH_tasks_G[Index].sRunMe = 0;
return Index;
}
//删除任务
unsigned char SCH_Delete_Task(unsigned char TASK_INDEX)
{
unsigned char Return_code;
if(SCH_tasks_G[TASK_INDEX].pTask == 0)
{
//这里没有任务。。。设置全局错误变量
Error_code_G = ERROR_SCH_CANOT_DELETE_TASK;
Return_code = RETURN_ERROR;//返回错误代码
}
else
{
Return_code = RETURN_NORMAL;
//删除任务
SCH_tasks_G[TASK_INDEX].pTask = 0x0000;
SCH_tasks_G[TASK_INDEX].sDelay = 0;
SCH_tasks_G[TASK_INDEX].sPeriod = 0;
SCH_tasks_G[TASK_INDEX].sRunMe = 0;
}
return Return_code;
}
PS:上面代码仅供参考,涉及中断保护没有给出,随便使用,没有版权,后果自负。
这种结构易于维护,代码可读性高,写程序的时候注意一下时间片和执行时间,可以确定程序运行时间。
再有就是常常需要休眠降低功耗的场合灰常适用。
|