第07章 时间片调度
约 743 字大约 2 分钟
2026-01-19
7.1 核心知识点
在FreeRTOS中,同等优先级的任务会轮流分享相同的CPU时间,这个时间被称为时间片。在这里,一个时间片的长度等同于SysTick中断的周期。
相关宏
configTICK_RATE_HZ 滴答频率,每个时间片时长等于一个滴答周期
configUSE_TIME_SLICING 是否启用控制时间片调度,默认是开启的7.2 案例
① 需求
task1:通过串口打印task1的运行次数,设置任务优先级为2。
task2:通过串口打印task2的运行次数,设置任务优先级为2。
为了更好观察现象,滴答定时器的中断频率设置为50ms中断一次(一个时间片)。② 效果

③ 代码
FreeRTOSConfig.h
添加如下配置项:
// 开启时间片调度(不写也可以,默认就是开启的)
#define configUSE_TIME_SLICING 1
// 设置滴答频率为20Hz(滴答周期是50ms,每个时间片是50ms)
#define configTICK_RATE_HZ 20App_Task.c
任务函数中进入临界区可以防止 printf() 串口输出过程中被打断!
#include "App_Task.h"
// 任务1 ------------------------------------
// 任务1函数的原型
void task1_callback(void *pvParameters);
// 任务1名称
#define TASK1_NAME "task1"
// 任务1堆栈大小
#define TASK1_STACK_SIZE 128
// 任务1的优先级
#define TASK1_PRIORITY 2
// 任务1的句柄
TaskHandle_t task1_handle;
// 任务2 ------------------------------------
// 任务2函数的原型
void task2_callback(void *pvParameters);
// 任务2名称
#define TASK2_NAME "task2"
// 任务2堆栈大小
#define TASK2_STACK_SIZE 128
// 任务2的优先级
#define TASK2_PRIORITY 2
// 任务2的句柄
TaskHandle_t task2_handle;
/**
* @brief 启动 FreeRTOS 任务管理
*
*/
void App_Task_Start(void)
{
// 进入临界区
taskENTER_CRITICAL();
// 创建任务1
xTaskCreate(task1_callback, TASK1_NAME, TASK1_STACK_SIZE, NULL, TASK1_PRIORITY, &task1_handle) == pdPASS ? printf("任务1创建成功! \n") : printf("任务1穿件失败! \n");
// 创建任务2
xTaskCreate(task2_callback, TASK2_NAME, TASK2_STACK_SIZE, NULL, TASK2_PRIORITY, &task2_handle) == pdPASS ? printf("任务2创建成功! \n") : printf("任务2穿件失败! \n");
// 退出临界区
taskEXIT_CRITICAL();
// 启动任务调度器 ( vTaskStartScheduler() 后面的代码不会被执行)
printf("任务调度器启动... \n");
vTaskStartScheduler();
}
// 任务1函数的实现
void task1_callback(void *pvParameters)
{
printf("任务1启动... \n");
// 定义变量,用于统计任务1执行的次数
uint32_t count = 0;
while (1)
{
// 进入临界区,防止打印过程被打断
taskENTER_CRITICAL();
// 切换LED1状态
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
// 计数+1
count++;
// 打印任务1执行的次数
printf("任务1执行次数: %d \n", count);
// 延时10ms
HAL_Delay(10);
// 退出临界区
taskEXIT_CRITICAL();
}
}
// 任务2函数的实现
void task2_callback(void *pvParameters)
{
printf("任务2启动... \n");
// 定义变量,用于统计任务2执行的次数
uint32_t count = 0;
while (1)
{
// 进入临界区,防止打印过程被打断
taskENTER_CRITICAL();
// 切换LED2状态
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
// 计数+1
count++;
// 打印任务2执行的次数
printf("任务2执行次数: %d \n", count);
// 延时10ms
HAL_Delay(10);
// 退出临界区
taskEXIT_CRITICAL();
}
}