基于时间系统的状态机

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;/*缺省*/

}

原文地址:https://www.cnblogs.com/jieruishu/p/6774880.html