一、任务调度器

1. 调度器结构体

函数指针和指针函数:C语言基础知识:函数指针&指针函数(定义格式、作用及用法说明)_指针函数的定义-CSDN博客

PS: 函数指针本身上还是一个指针,和一般指针没有区别,指向函数的执行地址

1
2
3
4
5
6
7
//调度器类型的结构体类型声明
//任务结构
typedef struct {
void (*task_func)(void);//函数指针
uint32_t rate_ms;//任务运行周期
uint32_t last_run;//上次运行时间
} scheduler_task_t;

typedef struct {} scheduler_task_t;是⼀种定义新结构体类型的⽅式,这⾥定义 了⼀个名为 scheduler_task_t 的结构体类型。这个结构体类型包含三个成员。

  • void *task_func(void);定义了一个函数指针,用于储存任务函数的地址,便于进行任务调度

  • rate_ms表示任务具体的执行周期

  • last_run⽤于存储任务上次运⾏的时间戳(以毫秒为单位)。该成员⽤于 记录任务上⼀次被调度执⾏的时间点,以便计算任务是否需要再次执⾏

静态任务数组,每个任务包括任务函数,执行周期,和上次执行时间

1
2
3
4
5
6
7
8
9
10
void Led_task(){

}

//定义调度器类型的变量 任务
//任务数组
//给scheduler_task_t类型变量tasks赋初值
static scheduler_task_t tasks[] ={
{Led_task,1000,0}//定义一个任务,任务函数为Led_Proc,执行周期为1000毫秒,初始上次运行时间为0
};

2. 调度器初始化

1
2
3
4
void scheduler_init(void){
//计算任务数组中任务函数的个数,结果储存在tasks_num中
tasks_num = sizeof(tasks)/sizeof(scheduler_task_t);
}

3. 调度器函数

遍历任务数组,检查是否有任务需要进行,如果系统当前时间超过任务的执行周期,那么执行任务变更,并且更新上次运行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
void scheduler_run(void){
/*任务轮询*/
for(uint8_t i=0; i< tasks_num; i++){
//获取当前时间(毫秒)
uint8_t time_now = HAL_GetTick();
//检查任务是否到达当前时间点
if(time_now >= tasks[i].rate_ms + tasks[i].last_run){
//更新任务的上次运行时间,保存时间戳
tasks[i].last_run = time_now;//保存当前时间
tasks[i].task_func();//执行对应指向的任务
}
}
}