前面所有的任务都是放在了一个简易的时间片里。这个时间片无优先级、动态调度功能。
一、任务结构体
typedef void(*TASK) (void); //任务函数指针
typedef struct
{
unsigned char run; //任务状态
unsigned char setTime; //设定时间
unsigned char timer; //计时器
TASK taskHook; //任务函数
}TaskComponent_s;
意味着一个任务需要占用5个字节Ram或Rom;
二、定时
需要一个systick,在定时器里固定递增:
void Timer2_Istr(void)
{
if(TC2IF)
{
TC2IF = 0;
Systick++;
}
}
三、初始化任务列表
//如Ram不足,可将此表定义于ROM中,但定义后将无法更改运行状态及运行时间
TaskComponent_s Task_Comps[]=
{
//任务状态 设定时间 计时 任务函数
{1,1,0,LEDApp_EffectHandle},
{0,100,0,LEDApp_Indicate},
{0,100,0,LEDApp_Connect},
{0,100,0,LEDApp_EachTraverse},
{1,8,0,Keyboard_Event},
{0,20,0,Btn_LongPress},
{0,1,0,Keyboard_Macro},
{1,0,0,Keyboard_Report},
{0,0,0,UserProtocol_Deal},
{0,200,0,UserProtocol_OverTime},
{0,20,0,Keyboard_AutoSleep},
};
四、任务调度
static unsigned char systickback=0;
/// @brief 任务调度
/// @param
void Task_Handler(void)
{
unsigned char time; //计算间隔时间
if(systickback<=Systick)
time = (u8)(Systick-systickback);
else
time = (u8)(0XFF-systickback+Systick+1);
systickback = Systick;
for(unsigned char i=0;i<sizeof(Task_Comps)/sizeof(TaskComponent_s);i++)
{
if(Task_Comps[i].run) //查询运行状态
{
Task_Comps[i].timer += time; //计时
if(Task_Comps[i].timer>=Task_Comps[i].setTime) //到达设定时间运行任务
{
Task_Comps[i].timer = 0;
Task_Comps[i].taskHook();
}
}
}
}
五、任务状态控制
/// @brief 任务运行状态控制
/// @param order 任务序号
/// @param run 运行状态
void Task_State(unsigned char order,unsigned char run)
{
if(order>=sizeof(Task_Comps)/sizeof(TaskComponent_s))
return;
Task_Comps[order].run = run;
Task_Comps[order].timer = 0;
}
六、任务时间设置
/// @brief 任务设定时间设置
/// @param order 任务序号
/// @param time 时间,单位毫秒
void Task_TimeSet(unsigned char order,unsigned char time)
{
if(order>=sizeof(Task_Comps)/sizeof(TaskComponent_s))
return;
Task_Comps[order].setTime = time;
Task_Comps[order].timer = 0;
}