FreeRTOS_时间管理

犀利的毛毛虫 发布于 2025-03-09 258 次阅读


延时函数介绍(了解)

  1. vTaskDelay():相对延时。从执行vTaskDelay()函数开始,直到指定延时的时间结束。
  2. xTaskDelayUntil():绝对延时。将整个任务的运行周期视为一个整体,适用于需要以固定频率定期执行的任务。

假设有一个定时器,每隔1秒触发一次,希望在每次触发时执行某个任务。如果使用 vTaskDelay 来实现,那么你只能实现任务每秒执行一次,而不能确保任务在每秒的开始时刻执行。但如果你使用 xTaskDelayUntil,你可以指定任务在每秒的开始时刻执行,即使任务执行的时间不同。

延时函数演示实验(掌握)实验目标

学习 FreeRTOS延时函数的使用,了解相对延时和绝对延时的区别:

  • start_task:用来创建其他的2个任务。
  • task1:用于展示相对延时函数vTaskDelay ( )的使用。
  • task2:用于展示绝对延时函数vTaskDelayUntil( )的使用。

为了观察两个延时函数的区别,将使用LED1 和 LED2的翻转波形来表示。

freertos_demo.c代码清单

#include "freertos_demo.h"
/* freertos相关的头文件,必须的 */
#include "FreeRTOS.h"
#include "task.h"
/* 需要用到的其他头文件 */
#include "LED.h"
#include "Key.h"

/* 启动任务的配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
void start_task(void *pvParameters);

/* 任务1的配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
void task1(void *pvParameters);

/* 任务2的配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
void task2(void *pvParameters);



/**
 * @description: 启动FreeRTOS
 * @return {*}
 */
void freertos_start(void)
{
    /* 1.创建一个启动任务 */
    xTaskCreate((TaskFunction_t)start_task,               // 任务函数的地址
                (char *)"start_task",                     // 任务名字符串
                (configSTACK_DEPTH_TYPE)START_TASK_STACK, // 任务栈大小,默认最小128,单位4字节
                (void *)NULL,                             // 传递给任务的参数
                (UBaseType_t)START_TASK_PRIORITY,         // 任务的优先级
                (TaskHandle_t *)&start_task_handle);      // 任务句柄的地址

    /* 2.启动调度器:会自动创建空闲任务 */
    vTaskStartScheduler();
}

/**
 * @description: 启动任务:用来创建其他Task
 * @param {void} *pvParameters
 * @return {*}
 */
void start_task(void *pvParameters)
{
    /* 进入临界区:保护临界区里的代码不会被打断 */
    taskENTER_CRITICAL();

    /* 创建3个任务 */
    xTaskCreate((TaskFunction_t)task1,
                (char *)"task1",
                (configSTACK_DEPTH_TYPE)TASK1_STACK,
                (void *)NULL,
                (UBaseType_t)TASK1_PRIORITY,
                (TaskHandle_t *)&task1_handle);
    xTaskCreate((TaskFunction_t)task2,
                (char *)"task2",
                (configSTACK_DEPTH_TYPE)TASK2_STACK,
                (void *)NULL,
                (UBaseType_t)TASK2_PRIORITY,
                (TaskHandle_t *)&task2_handle);

    /* 启动任务只需要执行一次即可,用完就删除自己 */
    vTaskDelete(NULL);

    /* 退出临界区 */
    taskEXIT_CRITICAL();
}

/**
 * @description: 任务一:实现LED1每500ms闪烁一次
 * @param {void} *pvParameters
 * @return {*}
 */
void task1(void *pvParameters)
{

    while (1)
    {
        // printf("task1运行...\r\n");
        LED_Toggle(LED1_Pin);
        HAL_Delay(20);
        vTaskDelay(500);
    }
}

/**
 * @description: 任务二:实现LED2每500ms闪烁一次
 * @param {void} *pvParameters
 * @return {*}
 */
void task2(void *pvParameters)
{
    TickType_t pxPreviousWakeTime = xTaskGetTickCount();
    while (1)
    {
        // printf("task2运行...\r\n");
        LED_Toggle(LED2_Pin);
        HAL_Delay(20);
        vTaskDelayUntil(&pxPreviousWakeTime,500);
    }
}