基于时间系统的状态机
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;/*缺省*/
}