基于stm32HAL库的简易调度器

前言

大家好,我是一名电子信息专业的初学者,为了更好地准备学习FreeRTOS,自己动手实现一个简易版的任务调度器。使用的是蓝桥杯的板子,但主要目的是为了加深对嵌入式系统任务管理的理解。还有就是看到这种调度器的教程CSDN上很少。

 调度器简介

这个调度器是为STM32系列单片机设计的,使用了HAL库进行开发。它实现了基于优先级的抢占式任务调度,能够高效管理多个任务的执行。调度器的设计目标是轻量级、易于移植,并且功能实用,特别适合资源受限的嵌入式系统。

基本原理

调度器基本原理(基于我的代码讲解)

1. 初始化调度器:


 在`scheduler_init`函数中,调度器初始化任务计数器,并添加一个空闲任务。空闲任务的优先级最低,用于在没有其他任务可执行时占用CPU。

2. 任务管理:


 通过`addTask`和`addTaskWithPriority`函数,用户可以添加任务到调度器中。每个任务都有一个函数指针、执行周期、名称和优先级。任务被存储在一个全局的任务数组中,最大支持10个任务。

3. 优先级调度:


 任务被分为四个优先级:空闲、低、中、高。高优先级任务可以抢占低优先级任务的执行。任务在添加时会根据优先级进行排序,确保高优先级任务优先执行。

4. 时间片轮询:


 在`schedulerRun`函数中,调度器通过一个无限循环不断检查任务列表。对于每个任务,调度器会检查其是否达到执行周期。如果达到,任务将被执行,并更新其上次执行时间。

5. CPU使用率统计:


 调度器通过统计总循环次数和空闲循环次数来计算CPU使用率。每秒更新一次CPU使用率,提供系统资源使用情况的实时监控。

6. 任务性能监控:


 调度器记录每个任务的执行次数、执行时间等信息。通过`getTaskStats`函数,用户可以获取任务的性能统计信息,包括总执行次数、平均执行时间、最大和最小执行时间等。

7. 动态调整和控制:


 调度器支持动态调整任务的执行周期和优先级,通过`changeTaskPeriod`和`changeTaskPriority`函数实现。这使得系统能够根据实际需求灵活调整任务的执行策略。


 

功能特性

多任务管理:支持最多10个并发任务的管理。
优先级调度:支持4级优先级(空闲、低、中、高)的任务调度。
抢占式调度:高优先级任务可以抢占低优先级任务的执行。
灵活的任务控制:支持任务的添加、暂停、恢复、删除等操作。
任务状态监控:可获取任务执行次数、执行时间等统计信息。
精确的CPU使用率统计:提供系统CPU使用率的实时监控,支持浮点数精度。
低资源占用:设计轻量,适合资源受限的嵌入式系统。
周期动态调整:支持在运行时动态调整任务执行周期。
任务性能分析:提供任务执行时间统计,包括最大、最小和平均执行时间。

此调度器的优缺点

优点:
轻量级设计,适合资源受限的系统。
支持多任务管理和优先级调度,能够有效提高系统的响应速度。
 提供了丰富的任务管理接口,使用灵活。
缺点:
由于是简易版,功能上可能不如成熟的商业调度器全面。
目前仅支持最多10个任务,适用范围有限。
 需要手动调整任务优先级和周期,自动化程度不高。

结语

通过实现这个简易调度器,希望能对同样在学习嵌入式系统的朋友们有所帮助,也欢迎大家提出宝贵的意见和建议。代码放最后了


 

 代码(直接复制粘贴即可)

scheduler.c

#include "scheduler.h"
//定义任务列表
TASK tasks[MAX_TASKS];//任务列表
volatile uint8_t task_count = 0;//已入栈的任务个数


//CPU使用率统计
static uint32_t total_counter = 0;  // 总循环次数计数
static uint32_t idle_counter = 0;  // 空闲计数器
static float cpu_usage = 0.0f;     // CPU使用率


//初始化调度器
void scheduler_init(void){
    task_count = 0;//初始化任务计数器
    //CPU使用率计算相关变量
    idle_counter = 0;
    total_counter=0;
    cpu_usage = 0;
    // 添加空闲任务(最低优先级)
    addTaskWithPriority(idleTask, 1, "idle", TASK_PRIORITY_IDLE);
}


//添加任务,默认为中优先级
SchedulerError_t addTask(void (*task)(void),//任务函数
                        uint32_t period,//执行周期
                        char *name){//任务名称
    return addTaskWithPriority(task,period,name,TASK_PRIORITY_MEDIUM);
}


SchedulerError_t addTaskWithPriority(void (*task)(void),//任务函数
                        uint32_t period,//执行周期      
                        char *name,//任务名称
                        TASK_PRIORITY priority)//优先级
{
        if(task==NULL)//任务为空
    {
        return SCHEDULER_ERROR_NULL_FUNC;
    }
    if(task_count>=MAX_TASKS)//任务队列已满
    {
        return SCHEDULER_ERROR_FULL;
    }
    tasks[task_count].task=task;
    tasks[task_count].period=period;
    tasks[task_count].name=name;
    tasks[task_count].last_time=HAL_GetTick();//获取当前时间作为初始化时间
    tasks[task_count].STATE=TASK_READY;
    tasks[task_count].priority=priority;
    tasks[task_count].exec_time = 0;
    tasks[task_count].exec_count = 0;
    tasks[task_count].max_exec_time = 0;
    tasks[task_count].min_exec_time = 0;
    tasks[task_count].total_exec_time = 0;
    task_count++;
    //按优先级对任务排序
    sortTasksByPriority();
    return SCHEDULER_OK;
}


//调度器运行
void schedulerRun(void){
    while(1){
        total_counter++;//总循环次数计数,每次循环计数
        uint32_t start_time=HAL_GetTick();//进入函数的时间
        uint8_t tasks_executed=0;//记录是否有任务执行

    for(uint8_t i=0;icurrentTime){//发生溢出
            //实际经过时间
            overtime=0xFFFFFFFF-tasks[i].last_time+currentTime+1;}
        else{overtime=currentTime-tasks[i].last_time;}

        if(tasks[i].STATE==TASK_READY && (overtime>=tasks[i].period)){
            //执行任务
            uint32_t task_start=HAL_GetTick();//任务开始时间
            tasks[i].task();
            uint32_t task_end=HAL_GetTick();//任务结束时间
            if(tasks[i].priority!=TASK_PRIORITY_IDLE)tasks_executed=1;//空闲任务不统计
            //更新任务信息统计
            tasks[i].last_time=task_end;//获取任务执行完后的最新时间
            tasks[i].exec_time=task_end-task_start;//任务执行时间
            tasks[i].exec_count++;//任务执行次数
            tasks[i].total_exec_time += tasks[i].exec_time;//任务总执行时间 
            tasks[i].max_exec_time = tasks[i].exec_time > tasks[i].max_exec_time ? tasks[i].exec_time : tasks[i].max_exec_time;//任务最大执行时间
            tasks[i].min_exec_time = tasks[i].exec_time < tasks[i].min_exec_time ? tasks[i].exec_time : tasks[i].min_exec_time;//任务最小执行时间
            
            
            //高优先级执行完后立即检查下一个任务
            //不等待整个列表扫描完(抢占式调度)
            if(tasks[i].priority>TASK_PRIORITY_LOW)
            {
                if(i==task_count-1||(tasks[i].priority>tasks[i+1].priority))
                {//此处-1是为了抵消i++,for循环在执行完一次循环体后会做一次i++
                    //i=-1;
                    break;//此处使用break代替i=-1,避免一直卡在for循环里无法执行其他操作(CPU利用率统计)
                }    
            }
        }
    }//for结束

    //更新CPU使用率统计()只在系统使用初期
    if(!tasks_executed){//如果处于空闲状态
        idle_counter++;
    }


    //每秒计算一次cpu使用率
    static uint32_t last_usage_updata=0;//上一次使用时间
    if(HAL_GetTick()-last_usage_updata>=1000)//每秒计算一次
    {
        if(total_counter>0){
            cpu_usage=100.0f-((idle_counter*100.0f)/total_counter);
        }
        idle_counter=0;
        total_counter=0;
        last_usage_updata=HAL_GetTick();
    }
    }//while结束
}//schedulerRun函数结束



//获取任务性能统计
SchedulerError_t getTaskStats(uint8_t taskID, TaskStats_t *stats)
{
    if(taskID >= task_count || stats == NULL){
        return SCHEDULER_ERROR_INVALID_ID;//ID无效
    }
    stats->total_executions = tasks[taskID].exec_count;//总执行次数
    if(tasks[taskID].exec_count>0){ //防止除以0
        stats->avg_exec_time = tasks[taskID].total_exec_time / tasks[taskID].exec_count;//平均执行时间
    }
    else{
        stats->avg_exec_time = 0;//如果执行次数为0,则平均执行时间为0
    }
    stats->max_exec_time = tasks[taskID].max_exec_time;//最长执行时间
    stats->min_exec_time = tasks[taskID].min_exec_time;//最短执行时间
    stats->total_exec_time = tasks[taskID].total_exec_time;//总执行时间
    return SCHEDULER_OK;
}





// 任务管理增强功能 - 新增函数
// 暂停任务
SchedulerError_t suspendTask(uint8_t taskID){
    if(taskID>=task_count){
        //ID超出当前已有任务数
        return SCHEDULER_ERROR_INVALID_ID;//无效ID
    }
    tasks[taskID].STATE=TASK_SUSPENDED;//暂停任务
    return SCHEDULER_OK;
}     


// 恢复任务
SchedulerError_t resumeTask(uint8_t taskID){
    if(taskID>=task_count){
        //ID超出当前已有任务数
        return SCHEDULER_ERROR_INVALID_ID;//无效ID
    }
    tasks[taskID].STATE=TASK_READY ;//恢复任务
    tasks[taskID].last_time=HAL_GetTick();//更新恢复后的时间防止恢复后马上执行
    return SCHEDULER_OK;
}


// 删除任务
SchedulerError_t deleteTask(uint8_t taskID){
    if(taskID>=task_count){
        //ID超出当前已有任务数
        return SCHEDULER_ERROR_INVALID_ID;//无效ID
    }
    for(uint8_t i=taskID;i= task_count){
        return SCHEDULER_ERROR_INVALID_ID; // 无效ID
    }
    if(taskInfo == NULL){
        return SCHEDULER_ERROR_NULL_FUNC; // 改用更合适的错误代码
    }
    //赋值任务信息
    *taskInfo=tasks[taskID];
    return SCHEDULER_OK;
}


// 通过名称查找任务
uint8_t findTaskByName(char *name)         
{
    if(name == NULL){
        return MAX_TASKS;//返回无效索引
    }
    for(uint8_t i=0;i= 0 && tasks[j].priority < temp.priority){
            tasks[j + 1] = tasks[j];
            j--;
        }
        
        tasks[j + 1] = temp;
    }
}




// 修改任务优先级
SchedulerError_t changeTaskPriority(uint8_t taskID, uint8_t newPriority){
    //检查ID是否有效
    if(taskID>=task_count){return SCHEDULER_ERROR_INVALID_ID;}
    //修改优先级
    tasks[taskID].priority=newPriority;
    //重新排序
    sortTasksByPriority();
    return SCHEDULER_OK;
}

// 修改任务周期
SchedulerError_t changeTaskPeriod(uint8_t taskID, uint32_t newPeriod){
    //检查ID是否有效
    if(taskID>=task_count){return SCHEDULER_ERROR_INVALID_ID;}
    //防止周期为0
    if(newPeriod==0){newPeriod=1;}
    //修改周期
    tasks[taskID].period=newPeriod;
    return SCHEDULER_OK;
}

// 重置任务时间(使下次立即执行)
SchedulerError_t resetTaskTime(uint8_t taskID){
    if(taskID >= task_count){
        return SCHEDULER_ERROR_INVALID_ID;
    }
    
    // 将上次执行时间设置为很久以前,确保下次检查时会立即执行
    tasks[taskID].last_time = HAL_GetTick() - tasks[taskID].period;
    return SCHEDULER_OK;
}



//空闲任务实现
void idleTask(void){
    __NOP();
}


//测试任务
void task1(void){
    static uint32_t n1=0;
    char str[10];
	n1++;
    //LCD_Clear(Black);
    LCD_DisplayStringLine(Line0,(uint8_t *)"task1");
    sprintf(str,"n1:%d",n1);
    LCD_DisplayStringLine(Line1,(uint8_t *)str);
    

    }


void task2(void){
    static uint32_t n2=0;
    char str[10];
	n2++;
    //LCD_Clear(Black);
    LCD_DisplayStringLine(Line2,(uint8_t *)"task2");
    sprintf(str,"n2:%d",n2);
    LCD_DisplayStringLine(Line3,(uint8_t *)str);


    }

//CPU使用率监控任务
void cpu_monitor_task(void) {
    char str[20];
    float usage = getCPUUsage();
    
    // 显示CPU使用率
    sprintf(str, "CPU: %f%%    ", usage);
    LCD_DisplayStringLine(Line4, (uint8_t *)str);
}


scheduler.h文件

#ifndef SCHEDULER_H
#define SCHEDULER_H

/**
 * @file scheduler.h
 * @brief 轻量级嵌入式实时任务调度器头文件
 * @details 该调度器适用于STM32系列单片机,支持多任务管理和优先级调度
 */

#include "main.h"
#include "gpio.h"
#include "lcd.h"

/** @brief 任务最大数量定义 */
#define MAX_TASKS 10 

/**
 * @brief 任务状态枚举
 * @details 定义任务的运行状态
 */
typedef enum {
    TASK_SUSPENDED = 0,  /**< 任务暂停状态 */
    TASK_READY          /**< 任务就绪状态 */
} TASK_STATE;

/**
 * @brief 任务优先级枚举
 * @details 定义任务的4级优先级
 */
typedef enum {
    TASK_PRIORITY_IDLE = 0,  /**< 空闲优先级(最低),仅用于空闲任务 */
    TASK_PRIORITY_LOW,       /**< 低优先级 */
    TASK_PRIORITY_MEDIUM,    /**< 中优先级(默认) */
    TASK_PRIORITY_HIGH       /**< 高优先级(最高) */
} TASK_PRIORITY;

/**
 * @brief 调度器错误代码枚举
 * @details 定义API函数可能返回的错误代码
 */
typedef enum {
    SCHEDULER_OK = 0,           /**< 操作成功 */
    SCHEDULER_ERROR_FULL,       /**< 任务列表已满 */
    SCHEDULER_ERROR_NULL_FUNC,  /**< 任务函数为空 */
    SCHEDULER_ERROR_INVALID_ID  /**< 无效的任务ID */
} SchedulerError_t;

/**
 * @brief 任务结构体
 * @details 定义任务的属性和状态信息
 */
typedef struct {
    void (*task)(void);     /**< 任务函数指针 */
    uint32_t period;        /**< 任务执行周期(ms) */
    uint32_t last_time;     /**< 任务上次执行时间 */
    uint8_t STATE;          /**< 任务状态(TASK_STATE枚举) */
    char *name;             /**< 任务名称 */
    uint8_t priority;       /**< 任务优先级(TASK_PRIORITY枚举) */
    uint32_t exec_time;     /**< 上次任务执行时间(ms) */
    uint32_t exec_count;    /**< 任务执行次数 */
    uint32_t max_exec_time; /**< 任务最大执行时间(ms) */
    uint32_t min_exec_time; /**< 任务最小执行时间(ms) */
    uint32_t total_exec_time; /**< 任务总执行时间(ms) */
} TASK;

/**
 * @brief 任务性能统计结构体
 * @details 用于记录和分析任务执行性能
 */
typedef struct {
    uint32_t total_executions;    /**< 总执行次数 */
    uint32_t avg_exec_time;       /**< 平均执行时间(ms) */
    uint32_t max_exec_time;       /**< 最长执行时间(ms) */
    uint32_t min_exec_time;       /**< 最短执行时间(ms) */
    uint32_t total_exec_time;     /**< 总执行时间(ms) */
} TaskStats_t;

// /**
//  * @brief CPU负载监控结构体
//  * @details 用于监控系统CPU使用情况
//  */
// typedef struct {
//     uint8_t cpu_current_usage;    /**< CPU当前使用率(%) */
//     uint8_t cpu_average_usage;    /**< CPU平均使用率(%) */
//     uint8_t cpu_max_usage;        /**< CPU最大使用率(%) */
//     uint8_t cpu_min_usage;        /**< CPU最小使用率(%) */
//     uint32_t cpu_overload_time;   /**< CPU超载时间(>=90%)(ms) */
//     uint32_t cpu_sample_time;     /**< CPU采样时间(ms) */
// } CPUStatus_t;

/*---------------------- 全局变量声明 ----------------------*/
/** @brief 任务列表数组 */
extern TASK tasks[MAX_TASKS];
/** @brief 当前任务数量 */
extern volatile uint8_t task_count;

/*---------------------- 初始化函数 ----------------------*/
/**
 * @brief 调度器初始化
 * @details 初始化调度器,创建默认的空闲任务
 */
void scheduler_init(void);

/*---------------------- 任务管理函数 ----------------------*/
/**
 * @brief 添加任务(默认中优先级)
 * @param task 任务函数指针
 * @param period 执行周期(ms)
 * @param name 任务名称
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t addTask(void (*task)(void), uint32_t period, char *name);

/**
 * @brief 添加任务(指定优先级)
 * @param task 任务函数指针
 * @param period 执行周期(ms)
 * @param name 任务名称
 * @param priority 任务优先级
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t addTaskWithPriority(void (*task)(void), uint32_t period, 
                                    char *name, TASK_PRIORITY priority);

/**
 * @brief 暂停任务
 * @param taskID 任务ID
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t suspendTask(uint8_t taskID);

/**
 * @brief 恢复任务
 * @param taskID 任务ID
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t resumeTask(uint8_t taskID);

/**
 * @brief 删除任务
 * @param taskID 任务ID
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t deleteTask(uint8_t taskID);

/**
 * @brief 重置任务时间
 * @details 使任务在下次检查时立即执行
 * @param taskID 任务ID
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t resetTaskTime(uint8_t taskID);

/*---------------------- 调度器运行函数 ----------------------*/
/**
 * @brief 启动调度器
 * @details 开始调度并执行任务,此函数不会返回
 */
void schedulerRun(void);

/*---------------------- 优先级管理函数 ----------------------*/
/**
 * @brief 修改任务优先级
 * @param taskID 任务ID
 * @param newPriority 新优先级
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t changeTaskPriority(uint8_t taskID, uint8_t newPriority);

/**
 * @brief 按优先级排序任务列表
 * @details 使用插入排序算法,高优先级任务排在前面
 */
void sortTasksByPriority(void);

/*---------------------- 周期管理函数 ----------------------*/
/**
 * @brief 修改任务周期
 * @param taskID 任务ID
 * @param newPeriod 新周期(ms)
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t changeTaskPeriod(uint8_t taskID, uint32_t newPeriod);

/*---------------------- 信息查询函数 ----------------------*/
/**
 * @brief 获取当前任务数量
 * @return uint8_t 当前任务数
 */
uint8_t getTaskCount(void);

/**
 * @brief 获取CPU使用率
 * @return float CPU使用率(%)
 */
float getCPUUsage(void);

/**
 * @brief 获取任务信息
 * @param taskID 任务ID
 * @param taskInfo 任务信息结构体指针
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t getTaskInfo(uint8_t taskID, TASK *taskInfo);

/**
 * @brief 通过名称查找任务
 * @param name 任务名称
 * @return uint8_t 任务ID,若未找到返回MAX_TASKS
 */
uint8_t findTaskByName(char *name);

/**
 * @brief 获取任务性能统计
 * @param taskID 任务ID
 * @param stats 任务性能统计结构体指针
 * @return SchedulerError_t 操作结果
 */
SchedulerError_t getTaskStats(uint8_t taskID, TaskStats_t *stats);

/*---------------------- 测试函数 ----------------------*/
/**
 * @brief 空闲任务
 * @details 用于CPU使用率计算
 */
void idleTask(void);

/**
 * @brief 测试任务1
 * @details LED闪烁和LCD显示任务
 */
void task1(void);

/**
 * @brief 测试任务2
 * @details LED闪烁和LCD显示任务
 */
void task2(void);


/**
 * @brief CPU使用率监控任务
 * @details 用于监控CPU使用率并显示在LCD上
 */
void cpu_monitor_task(void);    



#endif /* SCHEDULER_H */




readme.txt

# 嵌入式实时任务调度器使用手册

## 1. 调度器简介

这是一个适用于STM32系列单片机的轻量级嵌入式实时任务调度器,专为蓝桥杯嵌入式比赛设计。该调度器实现了基于优先级的抢占式任务调度,可以高效管理多个任务的执行,简化嵌入式系统的开发流程。调度器具有代码轻量、易于移植、功能实用等特点,特别适合资源受限的嵌入式系统。

## 2. 功能特性

- **多任务管理**:支持最多10个并发任务的管理
- **优先级调度**:支持4级优先级(空闲、低、中、高)的任务调度
- **抢占式调度**:高优先级任务可以抢占低优先级任务的执行
- **灵活的任务控制**:支持任务的添加、暂停、恢复、删除等操作
- **任务状态监控**:可获取任务执行次数、执行时间等统计信息
- **精确的CPU使用率统计**:提供系统CPU使用率的实时监控,支持浮点数精度
- **低资源占用**:设计轻量,适合资源受限的嵌入式系统
- **周期动态调整**:支持在运行时动态调整任务执行周期
- **任务性能分析**:提供任务执行时间统计,包括最大、最小和平均执行时间

## 3. 调度器原理

### 基本原理

该调度器基于时间片轮询机制,定期检查每个任务是否到达执行周期。具体工作流程如下:

1. 初始化调度器,创建任务列表和默认的空闲任务
2. 循环扫描任务列表,检查每个处于就绪状态的任务是否达到执行周期
3. 如果任务达到执行周期,则立即执行该任务
4. 高优先级任务执行完毕后立即检查下一个任务(抢占式调度)
5. 统计CPU使用率和任务执行信息

### CPU使用率计算

调度器采用高精度的CPU使用率计算方法:
1. 统计总循环次数(total_counter)和空闲循环次数(idle_counter)
2. 每秒更新一次CPU使用率
3. CPU使用率 = 100% - (idle_counter * 100% / total_counter)
4. 使用浮点数计算,提供更精确的使用率显示

### 优先级管理

调度器支持4级优先级:
- `TASK_PRIORITY_IDLE (0)`:空闲优先级,仅用于空闲任务
- `TASK_PRIORITY_LOW (1)`:低优先级
- `TASK_PRIORITY_MEDIUM (2)`:中优先级(默认)
- `TASK_PRIORITY_HIGH (3)`:高优先级

高优先级任务将优先执行,并且可以打断低优先级任务的轮询周期。

## 4. 主要函数接口

### 初始化函数

```c
void scheduler_init(void);  // 调度器初始化
```

### 任务管理函数

```c
// 添加任务(默认中优先级)
SchedulerError_t addTask(void (*task)(void), uint32_t period, char *name);

// 添加任务(指定优先级)
SchedulerError_t addTaskWithPriority(void (*task)(void), uint32_t period, 
                                    char *name, TASK_PRIORITY priority);

// 暂停任务
SchedulerError_t suspendTask(uint8_t taskID);

// 恢复任务
SchedulerError_t resumeTask(uint8_t taskID);

// 删除任务
SchedulerError_t deleteTask(uint8_t taskID);

// 修改任务优先级
SchedulerError_t changeTaskPriority(uint8_t taskID, uint8_t newPriority);

// 修改任务周期
SchedulerError_t changeTaskPeriod(uint8_t taskID, uint32_t newPeriod);

// 重置任务时间(使下次立即执行)
SchedulerError_t resetTaskTime(uint8_t taskID);
```

### 调度器运行函数

```c
void schedulerRun(void);  // 启动调度器运行
```

### 信息查询函数

```c
// 获取当前任务数量
uint8_t getTaskCount(void);

// 获取CPU使用率(浮点数精度)
float getCPUUsage(void);

// 获取任务信息
SchedulerError_t getTaskInfo(uint8_t taskID, TASK *taskInfo);

// 通过名称查找任务
uint8_t findTaskByName(char *name);

// 获取任务性能统计
SchedulerError_t getTaskStats(uint8_t taskID, TaskStats_t *stats);
```

## 5. 使用示例

### 示例1:基本任务创建与运行

```c
#include "scheduler.h"

// 定义任务函数
void led_task(void) {
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);  // LED翻转
}

void lcd_update_task(void) {
    LCD_Clear(Black);
    LCD_DisplayStringLine(Line1, (uint8_t *)"Hello World");
}

int main(void) {
    // 系统初始化代码
    
    // 初始化调度器
    scheduler_init();
    
    // 添加任务
    addTask(led_task, 500, "LED_Task");  // LED每500ms闪烁一次
    addTask(lcd_update_task, 1000, "LCD_Task");  // LCD每1秒更新一次
    
    // 启动调度器
    schedulerRun();
    
    // 永远不会执行到这里
    while(1) {}
}
```

### 示例2:优先级任务管理

```c
#include "scheduler.h"

// 高优先级任务
void high_priority_task(void) {
    // 处理紧急事件
}

// 中优先级任务
void medium_priority_task(void) {
    // 常规数据处理
}

// 低优先级任务
void low_priority_task(void) {
    // 后台操作
}

int main(void) {
    // 系统初始化代码
    
    // 初始化调度器
    scheduler_init();
    
    // 添加不同优先级的任务
    addTaskWithPriority(high_priority_task, 100, "High_Task", TASK_PRIORITY_HIGH);
    addTask(medium_priority_task, 200, "Med_Task");  // 默认中优先级
    addTaskWithPriority(low_priority_task, 500, "Low_Task", TASK_PRIORITY_LOW);
    
    // 启动调度器
    schedulerRun();
    
    while(1) {}
}
```

### 示例3:CPU使用率监控(更新版)

```c
#include "scheduler.h"

void cpu_monitor_task(void) {
    char str[20];
    float usage = getCPUUsage();
    
    // 显示CPU使用率(浮点数精度)
    sprintf(str, "CPU: %.2f%%", usage);
    LCD_DisplayStringLine(Line4, (uint8_t *)str);
}

int main(void) {
    // 系统初始化代码
    
    // 初始化调度器
    scheduler_init();
    
    // 添加CPU监控任务
    addTask(cpu_monitor_task, 1000, "CPU_Monitor");
    
    // 添加其他任务...
    
    // 启动调度器
    schedulerRun();
    
    while(1) {}
}
```

### 示例4:任务性能分析

```c
#include "scheduler.h"

void performance_monitor_task(void) {
    // 获取指定任务的性能统计
    TaskStats_t stats;
    uint8_t taskID = findTaskByName("Critical_Task");
    
    if(taskID < MAX_TASKS) {
        if(getTaskStats(taskID, &stats) == SCHEDULER_OK) {
            char str[20];
            // 显示任务的平均执行时间
            sprintf(str, "Avg: %ldms", stats.avg_exec_time);
            LCD_DisplayStringLine(Line3, (uint8_t *)str);
            
            // 显示任务的最大执行时间
            sprintf(str, "Max: %ldms", stats.max_exec_time);
            LCD_DisplayStringLine(Line4, (uint8_t *)str);
            
            // 显示任务执行次数
            sprintf(str, "Count: %ld", stats.total_executions);
            LCD_DisplayStringLine(Line5, (uint8_t *)str);
        }
    }
}

int main(void) {
    // 系统初始化代码
    
    // 初始化调度器
    scheduler_init();
    
    // 添加性能监控任务
    addTask(performance_monitor_task, 2000, "Perf_Monitor");
    
    // 添加要监控的任务
    addTask(critical_task, 100, "Critical_Task");
    
    // 启动调度器
    schedulerRun();
    
    while(1) {}
}
```

### 示例5:动态调整任务周期

```c
#include "scheduler.h"

// 根据环境变化动态调整任务周期的例子
void adaptive_control_task(void) {
    static uint8_t mode = 0;
    uint8_t taskID;
    
    // 根据某些条件切换模式
    if(/* 检测到高速模式条件 */) {
        if(mode != 1) {
            // 找到需要调整的任务
            taskID = findTaskByName("Sensor_Task");
            if(taskID < MAX_TASKS) {
                // 高速模式,减少周期到50ms,更频繁采样
                changeTaskPeriod(taskID, 50);
            }
            mode = 1;
        }
    } else {
        if(mode != 0) {
            // 找到需要调整的任务
            taskID = findTaskByName("Sensor_Task");
            if(taskID < MAX_TASKS) {
                // 正常模式,恢复到200ms周期
                changeTaskPeriod(taskID, 200);
            }
            mode = 0;
        }
    }
}

int main(void) {
    // 系统初始化代码
    
    // 初始化调度器
    scheduler_init();
    
    // 添加传感器任务(初始周期200ms)
    addTask(sensor_task, 200, "Sensor_Task");
    
    // 添加自适应控制任务
    addTask(adaptive_control_task, 500, "Adaptive_Control");
    
    // 启动调度器
    schedulerRun();
    
    while(1) {}
}
```

## 6. 注意事项

1. 任务函数应尽量简短,避免长时间阻塞
2. 总任务数不能超过`MAX_TASKS`(默认为10)
3. 不要在任务中使用无限循环,否则将阻塞整个调度器
4. 高优先级任务执行频率不宜过高,以免占用过多CPU时间
5. 调度器运行后将进入无限循环,后续代码不会执行
6. 任务函数内不建议使用较长的延时函数
7. 对任务进行性能监控可能会略微增加系统开销
8. 优先级排序使用了插入排序算法以提高效率
9. CPU使用率计算每秒更新一次,使用浮点数提供更精确的显示

## 7. 错误代码说明

调度器的API函数会返回以下错误代码:

- `SCHEDULER_OK (0)`:操作成功
- `SCHEDULER_ERROR_FULL (1)`:任务列表已满
- `SCHEDULER_ERROR_NULL_FUNC (2)`:任务函数为空
- `SCHEDULER_ERROR_INVALID_ID (3)`:无效的任务ID

请在调用API函数后检查返回值,确保操作成功执行。

## 8. 任务性能统计

调度器提供了任务性能统计功能,可通过`getTaskStats`函数获取以下信息:

- 任务总执行次数
- 任务平均执行时间
- 任务最长执行时间
- 任务最短执行时间
- 任务总执行时间

这些信息对于系统性能分析和优化非常有用,特别是在需要精确控制任务执行时间的实时系统中。

---

以上就是调度器的基本使用方法,更多高级用法可以根据需求进行扩展。祝您在蓝桥杯比赛中取得好成绩!








你可能感兴趣的:(stm32,算法,嵌入式硬件,单片机)