TaskStruct
时间片轮询系统
时间片轮询法是一种比较简单易用的系统架构之一,它对于系统中的任务调度算法是分时处理。核心思路是把 CPU 的时间分时给各个任务使用。我们常用的定时方法是定时器,把调度器放在定时中,可以简单的实现时间片轮询法。
需要注意的是,这种方法的前提是执行的 每个任务都是短小精悍的,要不然一个任务执行的时间过长,大于其它任务设置的时间片值,那其它任务就无法保证按它预设的时间片来执行。
尤其需要注意任务中延时的使用,可能会产生不可预料的结果。如果任务内部需要延时的时候,或者说单个任务过长,需要保存任务执行到一半的状态,建议使用状态机切割长任务。
文件结构
polling.c
polling.h
源码
polling.c
#include "polling.h"
/*******************申明区***************************/
static TaskStruct task_list[];//任务组
/*******************可修改区***************************/
/*
简 要:创建任务区
详 细:无
*/
void task1()
{
static int i=0;
i++;
printf("执行任务%d\n",i);
if(i==10)
{
task_ONorOFF(1);
}
if(i==20)
{
task_ONorOFF(1);
i=0;
}
}
void task2()
{
LED1=~LED1;
}
/*
简 要:创建任务组
详 细:无
*/
static TaskStruct task_list[]=
{
{1 , 1000, 0, 1000, task1},
{1 , 500, 0, 500, task2},
//添加任务
};
/*******************不可修改区***************************/
/*
简 要:任务数量
详 细:无
*/
#define TASKS_MAX sizeof(task_list)/sizeof(task_list[0])
/*
简 要:任务调度器
详 细:设置一个1ms的定时器,将函数放置在中断函数里
参 数:无
返回值:无
*/
void task_schedule(void)
{
for(uint8_t i = 0 ; i < TASKS_MAX ; i++)//逐个任务时间处理,TASKS_MAS任务总数
{
if(task_list[i].timer)//距离下一次任务执行时间非0
{
task_list[i].timer--;//减去一个时间节拍
if(task_list[i].timer == 0) //距离下一次任务执行时间为0
{
task_list[i].timer = task_list[i].interval_time; //重装载任务间隔时间
task_list[i].run = 1;//任务就绪
}
}
}
}
/*
简 要:任务执行器
详 细:放置mian函数中的whlie循环中,while循环中仅此函数
参 数:无
返回值:无
*/
void task_process(void)
{
for(uint8_t i = 0 ; i<TASKS_MAX ; i++)//逐个任务处理
{
if(task_list[i].enable_flay)//是否为使能任务
{
if(task_list[i].run)//是否为就绪态
{
task_list[i].run = 0;//就绪态复位
task_list[i].task();//运行任务函数
}
}
}
}
/*
简 要:开启或关闭一个任务
详 细:无
参 数:任务编号
返回值:无
*/
void task_ONorOFF(uint8_t coding)
{
if(task_list[coding].enable_flay == 1)//判断是否为开启状态
{
task_list[coding].enable_flay = 0;
}
else//如果为关闭状态
{
task_list[coding].enable_flay = 1;
}
}
polling.h
#ifndef __POLLING_H
#define __POLLING_H
#include "sys.h"
/*
时间片轮询1.0
作者:nanqi
*/
/*
简 要:任务结构体
详 细:无
*/
typedef struct
{
uint8_t enable_flay;//任务使能标志位,0不需要运行,1需要运行
uint16_t timer;//还差多少时间就需要调度这个任务
uint8_t run;//任务是否就绪,0未就绪,就绪态
uint16_t interval_time;//任务运行的间隔问题,即每隔多久调度一次
void (*task)(void);//任务回调函数,即要运行的任务函数
}TaskStruct;
/*
简 要:函数申请区
详 细:无
*/
void task_process(void);//任务调度器
void task_schedule(void);//任务执行器
void task_ONorOFF(uint8_t coding);//开启或关闭一个任务
#endif
使用说明
task_schedule()
task_schedule():放置于对于型号单片机的中断中,建议设定定时器1ms延时
//定时器9中断服务函数
void TIM1_BRK_TIM9_IRQHandler(void)
{
if(TIM_GetITStatus(TIM9,TIM_IT_Update)==SET) //溢出中断
{
task_schedule();
}
TIM_ClearITPendingBit(TIM9,TIM_IT_Update); //清除中断标志位
}
task_process()
task_process():放置入main函数的while中
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //延时初始化
uart_init(115200); //串口初始化波特率为115200
TIM9_Int_Init(1000-1,168-1);
LED_Init(); //初始化与LED连接的硬件接口
while(1)
{
task_process();
}
}
任务创建
在这里申明出任务的属性,越靠前的任务优先级越高
/*
简 要:创建任务组
详 细:无
*/
static TaskStruct task_list[]=
{
{1 , 1000, 0, 1000, task1},
{1 , 500, 0, 500, task2},
//添加任务
};
任务属性参照
/*
简 要:任务结构体
详 细:无
*/
typedef struct
{
uint8_t enable_flay;//任务使能标志位,0不需要运行,1需要运行
uint16_t timer;//还差多少时间就需要调度这个任务
uint8_t run;//任务是否就绪,0未就绪,就绪态
uint16_t interval_time;//任务运行的间隔问题,即每隔多久调度一次
void (*task)(void);//任务回调函数,即要运行的任务函数
}TaskStruct;
然后在定义的任务中写出任务具体实现:
/*
简 要:创建任务区
详 细:无
*/
void task1()
{
static int i=0;
i++;
printf("执行任务%d\n",i);
if(i==10)
{
task_ONorOFF(1);
}
if(i==20)
{
task_ONorOFF(1);
i=0;
}
}
void task2()
{
LED1=~LED1;
}