大家好,我是一名电子信息专业的初学者,为了更好地准备学习FreeRTOS,自己动手实现一个简易版的任务调度器。使用的是蓝桥杯的板子,但主要目的是为了加深对嵌入式系统任务管理的理解。还有就是看到这种调度器的教程CSDN上很少。
这个调度器是为STM32系列单片机设计的,使用了HAL库进行开发。它实现了基于优先级的抢占式任务调度,能够高效管理多个任务的执行。调度器的设计目标是轻量级、易于移植,并且功能实用,特别适合资源受限的嵌入式系统。
在`scheduler_init`函数中,调度器初始化任务计数器,并添加一个空闲任务。空闲任务的优先级最低,用于在没有其他任务可执行时占用CPU。
通过`addTask`和`addTaskWithPriority`函数,用户可以添加任务到调度器中。每个任务都有一个函数指针、执行周期、名称和优先级。任务被存储在一个全局的任务数组中,最大支持10个任务。
任务被分为四个优先级:空闲、低、中、高。高优先级任务可以抢占低优先级任务的执行。任务在添加时会根据优先级进行排序,确保高优先级任务优先执行。
在`schedulerRun`函数中,调度器通过一个无限循环不断检查任务列表。对于每个任务,调度器会检查其是否达到执行周期。如果达到,任务将被执行,并更新其上次执行时间。
调度器通过统计总循环次数和空闲循环次数来计算CPU使用率。每秒更新一次CPU使用率,提供系统资源使用情况的实时监控。
调度器记录每个任务的执行次数、执行时间等信息。通过`getTaskStats`函数,用户可以获取任务的性能统计信息,包括总执行次数、平均执行时间、最大和最小执行时间等。
调度器支持动态调整任务的执行周期和优先级,通过`changeTaskPeriod`和`changeTaskPriority`函数实现。这使得系统能够根据实际需求灵活调整任务的执行策略。
多任务管理:支持最多10个并发任务的管理。
优先级调度:支持4级优先级(空闲、低、中、高)的任务调度。
抢占式调度:高优先级任务可以抢占低优先级任务的执行。
灵活的任务控制:支持任务的添加、暂停、恢复、删除等操作。
任务状态监控:可获取任务执行次数、执行时间等统计信息。
精确的CPU使用率统计:提供系统CPU使用率的实时监控,支持浮点数精度。
低资源占用:设计轻量,适合资源受限的嵌入式系统。
周期动态调整:支持在运行时动态调整任务执行周期。
任务性能分析:提供任务执行时间统计,包括最大、最小和平均执行时间。
通过实现这个简易调度器,希望能对同样在学习嵌入式系统的朋友们有所帮助,也欢迎大家提出宝贵的意见和建议。代码放最后了
#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);
}
#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 */
# 嵌入式实时任务调度器使用手册
## 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`函数获取以下信息:
- 任务总执行次数
- 任务平均执行时间
- 任务最长执行时间
- 任务最短执行时间
- 任务总执行时间
这些信息对于系统性能分析和优化非常有用,特别是在需要精确控制任务执行时间的实时系统中。
---
以上就是调度器的基本使用方法,更多高级用法可以根据需求进行扩展。祝您在蓝桥杯比赛中取得好成绩!