1根据各任务的周期执行时间确定轮询间隔,注意(轮询时间间隔只能比任务执行时间稍长,但一定不能断)
2 用一个定时器,基准定时为各任务的最小公倍数;软件计数器累加从而触发各任务标志(对任务进行字节编码)
3主函数中分别操作:Toggle_Task();//设置各标志,这里可以是非时间触发的事件
slect_task();//对任务标志进行字节解码:指针函数指向不同的具体函数
如果不是空函数(状态陷阱)就用指针函数调用各具体函数。
注意:
1 状态机编程思想要贯彻整个设计,即分层状态机,每个状态又分成各子状态。
2 各状态函数中的状态指示要用静态变量,即便被中断断开,下次还可以接着之前的状态继续进行。要注意异步事件时的现场保护。
3基于时间片和异步事件的任务触发要仔细分析优先级,对多事件触发如何处理(可以做变通方法。)
int main(void)
{ 初始化。。。 while(1) { switch(i) { case 0:if(TaskFlag.Flag0 == 1) Task0();break; case 1:if(TaskFlag.Flag1 == 1) Task1();break; case 2:if(TaskFlag.Flag2 == 1) Task2();break; case 3:if(TaskFlag.Flag3 == 1) Task3();break; case 4:if(TaskFlag.Flag4 == 1) Task4();break; case 5:if(TaskFlag.Flag5 == 1) Task5();break; default: i = 0;break; } if((++i)>=Task_Num) i = 0; }}void TIM3_IRQHandler(void) //TIM3 中断
{ if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除 TIM3 更新中断标志 CTimer++;//系统时间累加 TaskFlag.Flag0 = 1; }}void Task0(void)
{ TaskFlag.Flag0 = 0; if((CTimer & BITMAK_TASK1) == 0x01)//20ms 任务1 { TaskFlag.Flag1= 1; }f((CTimer & BITMAK_TASK2) == 0x02)//20ms 任务1
{ TaskFlag.Flag2= 1; }。。。
}
=========================架构2=============================
#define VOID_FUNC ((void *)0)
#typedef void pFunc_type(void)
pFunc_type present_task =VOID_FUNC;
typedef union TASKFLAG_BITS{
Uint8 taskall; struct{ Uint16 task0:1; Uint16 task1:1; Uint16 task2:1; Uint16 task3:1; Uint16 task4:1; Uint16 task5:1; Uint16 task6:1; Uint16 task7:1 }Flag;}TaskFlag_Bits,*TaskFlag_Bits_Pt;TaskFlag_Bits TaskFlag;
int main(void)
{ 初始化。。。 while(1) {Task_Trigger();//任务触发
Task_Select(); if (present_task != VOID_FUNC) present_task(); }}
void Task_Trigger(void)
{
/*至少有一个初始引导条件*/
if(某个条件具备)/*时间到或者异步事件触发*/
{
Taskflag.Flag.task1=1;
}
if(某个条件具备)
{
Taskflag.Flag.task2=1;
}
。。。。。
}
void Task_Select(void)
{
if (Taskflag.Flag.task0)
{ present_task = Task0; return; }if (Taskflag.Flag.task1)
{ present_task = Task1; return; }....
present_task = VOID_FUNC;/*缺省*/
}