FreeRTOS(7):时间片管理函数

📅 2026/8/1 21:07:28 👁️ 阅读次数 📝 编程学习
FreeRTOS(7):时间片管理函数

实验现象

使用串口助手,在串口助手下实现如下图所示:

笔者的延时函数好像有一点问题,现象应该是task1打印4次后切换到task2打印4次如此循环,但是笔者task1和2的打印次数都不对,但也算勉强体现出了想要结果,若有解决方法,可以在评论区写出或者私信笔者。

创建工程

选择上一个实验的Freertos_列表项的插入与删除,复制粘贴重命名为Freertos_时间片调度实验,打开别的江协科技的项目,选择System文件,复制其中的Delay.c和Delay.h文件,粘贴到Freertos_时间片调度实验的Hardware文件夹中。

编写代码

进入keil,按照下图顺序添加Delay.c和Delay.h文件

添加完成后进入Delay.c文件,因为江协科技的Delay函数使用了滴答计时器来实现延时,与FreeRTOS的冲突了,所以我们要更改一下,笔者使用的是TIM4定时器,如果有别的可以实现该实验功能的方法,可以在评论区或者私信笔者,下方是我的delay函数的代码:

#include "stm32f10x.h" #define TIM_DELAY TIM4 #define TIM_DELAY_CLK 72000000 /* 72MHz */ static uint8_t tim_delay_initialized = 0; static void TIM_Delay_Init(void) { if (tim_delay_initialized) return; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Prescaler = (TIM_DELAY_CLK / 1000000) - 1; // 1 MHz TIM_InitStruct.TIM_Period = 0xFFFF; TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM_DELAY, &TIM_InitStruct); TIM_Cmd(TIM_DELAY, ENABLE); tim_delay_initialized = 1; } void Delay_us(uint32_t xus) { if (xus == 0) return; TIM_Delay_Init(); TIM_SetCounter(TIM_DELAY, 0); while (TIM_GetCounter(TIM_DELAY) < xus); } void Delay_ms(uint32_t xms) { while (xms--) { Delay_us(1000); } } void Delay_s(uint32_t xs) { while (xs--) { Delay_ms(1000); } }

然后需要将Timer.c 中的中断函数中的内容和函数头上队列句柄删除,如不删除,会发生报错,删除内容如下图所示:

随后我们要去到FreeRTOSConfig.h文件中,将下图所示的宏定义改为20hz既一个时间片的时间为50ms

接下来就是修改FreeRTOS_Task函数中的内容,首先删除上一个实验与这个实验无关的内容,如列表参数,task1函数内的内容,task2函数内的内容等,下方是修改后的FreeRTOS_Task的代码:

#include "stm32f10x.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "led.h" #include "key.h" #include "serial.h" #include "timer.h" #include "delay.h" /* 任务参数 */ #define START_TASK_SIZE 128 #define START_TASK_PRIO 1 #define TASK1_SIZE 256 #define TASK1_PRIO 3 #define TASK2_SIZE 256 #define TASK2_PRIO 3 /* 任务句柄 */ TaskHandle_t start_task_handle; TaskHandle_t task1_handle; TaskHandle_t task2_handle; void Start_task(void *pvParameters); void task_1(void *pvParameters); void task_2(void *pvParameters); void FreeRTOS_Task(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); Key_Init(); LED_Init(); Serial_Init(); xTaskCreate((TaskFunction_t)Start_task, "Start_task", START_TASK_SIZE, NULL, START_TASK_PRIO, &start_task_handle); vTaskStartScheduler(); } void Start_task(void *pvParameters) { taskENTER_CRITICAL(); xTaskCreate((TaskFunction_t)task_1, "task_1", TASK1_SIZE, NULL, TASK1_PRIO, &task1_handle); xTaskCreate((TaskFunction_t)task_2, "task_2", TASK2_SIZE, NULL, TASK2_PRIO, &task2_handle); taskEXIT_CRITICAL(); vTaskDelete(NULL); } /* * task_1 :在一个时间片内每隔 10ms 打印一次计数,连续运行直至被切换 */ void task_1(void *pvParameters) { uint32_t Task1_Num = 0; while (1) { taskENTER_CRITICAL(); Task1_Num++; Serial_Sendstring("Task1_Num = "); Serial_SendNum(Task1_Num, 5); Serial_Sendstring("\r\n"); taskEXIT_CRITICAL(); Delay_ms(10); /* 轮询忙等 10ms,不释放 CPU */ } } /* * task_2 :在一个时间片内每隔 10ms 打印一次计数,连续运行直至被切换 */ void task_2(void *pvParameters) { uint32_t Task2_Num = 0; while (1) { taskENTER_CRITICAL(); Task2_Num++; Serial_Sendstring("Task2_Num = "); Serial_SendNum(Task2_Num, 5); Serial_Sendstring("\r\n"); taskEXIT_CRITICAL(); Delay_ms(10); /* 轮询忙等 10ms,不释放 CPU */ } }

随后运行,下载代码后就能在串口助手里看见现象了,再说一次,笔者的延时函数好像有一点问题,现象有误,若有解决方法可以私信或者在评论区内指出。