一、实验简介

本篇博客带大家完成 FreeRTOS 多任务创建 + 任务动态删除经典入门实验,非常适合新手理解 RTOS 多任务并发、任务优先级、任务生命周期、vTaskDelete 函数用法。

实验功能:

  1. 创建三个任务:开始任务、任务1、任务2

  2. 系统启动后,任务1、任务2同时并发运行,LED0、LED1 每秒翻转一次,串口打印运行信息

  3. 任务1计数运行5次后,动态删除任务2

  4. 任务2被删除后彻底停止运行,仅剩任务1独立运行

实验现象:

  • 前5秒:两个LED同时闪烁,串口同时打印两个任务运行日志

  • 5秒后:LED1停止闪烁,Task2不再打印,只有Task1持续运行

二、完整可运行代码

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"

//===================== 开始任务配置 =====================
#define START_TASK_SIZE 120
#define START_TASK_PRIO 1
TaskHandle_t StartTask_Hander;
void start_task( void * pvParameters );

//===================== 任务1配置 =====================
#define TASK1_TASK_SIZE 120
#define TASK1_TASK_PRIO 2
TaskHandle_t TASK1Task_Hander;
void task1_task( void * pvParameters );

//===================== 任务2配置 =====================
#define TASK2_TASK_SIZE 120
#define TASK2_TASK_PRIO 3
TaskHandle_t Task2Task_Hander;
void task2_task( void * pvParameters );

//主函数
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//中断分组4
	delay_init();	    				
	uart_init(115200);					
	LED_Init();		  					

	//创建开始任务
	xTaskCreate( (TaskFunction_t) 	start_task,
               (char *)			  	  "start_task", 
               (uint16_t) 				START_TASK_SIZE,
               (void *)					  NULL,
               (UBaseType_t) 			START_TASK_PRIO,
               (TaskHandle_t *)	  &StartTask_Hander );        
    
    vTaskStartScheduler();          //开启任务调度
}

//开始任务:负责创建所有业务任务,随后自删除
void start_task( void * pvParameters )
{
	//创建任务1
	xTaskCreate( (TaskFunction_t) 	task1_task,
               (char *)			  	  "task1_task", 
               (uint16_t) 				TASK1_TASK_SIZE,
               (void *)					  NULL,
               (UBaseType_t) 			TASK1_TASK_PRIO,
               (TaskHandle_t *)	  &TASK1Task_Hander ); 
	
	//创建任务2
	xTaskCreate( (TaskFunction_t) 	task2_task,
               (char *)			  	  "task2_task", 
               (uint16_t) 				TASK2_TASK_SIZE,
               (void *)					  NULL,
               (UBaseType_t) 			TASK2_TASK_PRIO,
               (TaskHandle_t *)	  &Task2Task_Hander ); 
							 
	//开始任务完成使命,自我删除
	vTaskDelete(StartTask_Hander);							 
}

//任务1:计数5次后删除任务2
void task1_task( void * pvParameters )
{
	char task1_num = 0;
	
	while(1)
	{
		task1_num++;
		
		//运行5次后删除任务2
		if(task1_num == 5)
		{
			printf("Task2 is delete \r\n");
			vTaskDelete(Task2Task_Hander);
		}
		
		LED0 = -LED0;
		vTaskDelay(1000);
		printf("Task1 is running  %d\r\n",task1_num);
	}
}

//任务2:持续闪烁打印,等待被删除
void task2_task( void * pvParameters )
{
	char task2_num =0;
	while(1)
	{
		task2_num++;
		LED1 = -LED1;
		vTaskDelay(1000);
		printf("Task2 is running  %d\r\n",task2_num);
	}
}

三、代码分层详细解析

1. 任务通用配置规范

FreeRTOS 所有任务都遵循四件套配置规范,这是标准模板:

  • 任务堆栈大小:规定任务占用的栈内存

  • 任务优先级:数值越大,优先级越高

  • 任务句柄:任务的唯一标识,用于操控任务(删除/挂起/恢复)

  • 任务函数:任务具体执行的业务逻辑

本实验优先级:任务2(3) > 任务1(2) > 开始任务(1)

2. Main 函数逻辑

main 函数在 FreeRTOS 中只做初始化和创建起始任务,不写业务代码:

  1. 配置中断分组、延时、串口、LED硬件初始化

  2. 唯一创建 开始任务

  3. 调用 vTaskStartScheduler() 启动RTOS调度,系统正式进入多任务运行

3. 开始任务(中转任务)

开始任务是 FreeRTOS 经典设计:只负责创建其他业务任务,随后自删

优势:系统启动更稳定,避免在调度未完全就绪时创建任务,是工程通用写法。

执行流程:创建任务1 → 创建任务2 → 自我删除,彻底释放资源。

4. 任务1(主控任务)

核心功能:计数监测 + 动态删除其他任务

  • 定义计数变量,每1秒自增一次

  • 计数等于5时,调用 vTaskDelete(任务2句柄) 杀死任务2

  • 持续翻转LED0、打印运行日志,永久运行

5. 任务2(被控制任务)

普通业务任务,无特殊逻辑:每秒翻转LED1、打印运行信息,一旦被删除,永久停止执行

四、整体运行时序流程

  1. 系统启动:硬件初始化完成,创建开始任务,开启调度器

  2. 任务初始化:开始任务创建任务1、任务2,随后自我销毁

  3. 并发运行阶段(0-5s):任务1、任务2同时抢占运行,双灯闪烁,双任务日志打印

  4. 任务删除时刻(第5s):任务1计数达到5,执行删除API,任务2彻底终止

  5. 单任务运行阶段(5s后):仅任务1持续运行,LED1定格、Task2日志不再输出

五、核心知识点总结

1. vTaskDelete 函数要点

  • 作用:删除一个已经创建的任务,回收任务堆栈和TCB资源

  • 传参:填写任务句柄可删除指定任务;填NULL删除自身

  • 删除后任务彻底结束,无法自动恢复

2. FreeRTOS 多任务核心特性

  • vTaskDelay() 的任务会主动让出CPU,实现伪并行并发

  • 优先级决定抢占顺序,空闲延时状态下高低优先级任务均可正常轮转

  • 所有业务任务必须包含 while(1) 死循环,否则运行一次就退出

3. 工程标准开发模板

新手固定套此流程写FreeRTOS代码,零报错:

  1. 定义所有任务(堆栈、优先级、句柄、函数声明)

  2. main函数仅做硬件初始化 + 创建开始任务

  3. 开始任务批量创建业务任务,随后自删

  4. 编写各任务while(1)业务逻辑

  5. 通过RTOS API动态管控任务(删除、挂起、恢复)

六、写 FreeRTOS 程序的【固定步骤】(万能模板)

以后写 FreeRTOS 代码,严格按这 6 步走,绝对不会错:

步骤 1:定义任务三要素

#define XXX_TASK_SIZE xx
#define XXX_TASK_PRIO x
TaskHandle_t XXXTask_Handler;
void xxx_task(void *pvParameters);

步骤 2:main 函数初始化硬件

NVIC配置、延时、串口、LED...

步骤 3:main 里只创建 “开始任务”

xTaskCreate(start_task,...);
vTaskStartScheduler();

步骤 4:开始任务里创建所有业务任务

xTaskCreate(任务1);
xTaskCreate(任务2);
...
vTaskDelete(NULL); // 删除自己

步骤 5:写业务任务逻辑

void task1_task(void *pvParameters)
{
    while(1)
    {
        // 你的功能代码
        vTaskDelay(xxx);
    }
}

步骤 6:使用 FreeRTOS API 控制任务(延时、删除、挂起等)

  • vTaskDelay()
  • vTaskDelete()
  • vTaskSuspend()
  • ...

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐