当前位置: 首页 > news >正文

2025最新超详细FreeRTOS入门教程:第二章 FreeRTOS任务创建

2025最新超详细FreeRTOS入门教程:第二章 FreeRTOS任务创建

摘要

在完成第一章 FreeRTOS 移植到 STM32 后,我们已经能够运行一个最小任务。本章将带你深入理解 任务(Task) 的概念、创建方式、运行机制和调度策略。
任务是 FreeRTOS 的核心,掌握任务的创建和使用,意味着你已经正式踏入 RTOS 世界。
2025最新超详细FreeRTOS入门教程

文章目录

  • 2025最新超详细FreeRTOS入门教程:第二章 FreeRTOS任务创建
    • 摘要
    • 一、任务的基本概念
      • 特点
    • 二、任务创建 API
      • 1. 动态创建任务
      • 2. 静态创建任务
    • 三、任务的优先级与调度
      • 调度策略
      • 示例
    • 四、任务创建实战
      • 示例:两个任务并发
    • 五、任务句柄的使用
      • 获取任务信息
    • 六、任务生命周期
    • 七、常见问题与解决方法
    • 八、经验分享
    • 九、总结


一、任务的基本概念

📌 在 裸机系统 中,程序代码通常放在 while(1) 循环中顺序执行,而 FreeRTOS 将应用划分为 多个任务,每个任务都可以看作一个独立的线程,内核负责任务的调度和切换。

特点

  • 每个任务都有自己的 堆栈空间
  • 内核根据 优先级调度算法 切换任务
  • 每个任务都像一个无限循环,通常以 for(;;)while(1) 形式实现
裸机程序
单一循环
FreeRTOS程序
任务1: LED闪烁
任务2: 串口打印
任务3: 数据处理

二、任务创建 API

FreeRTOS 提供了 xTaskCreate()xTaskCreateStatic() 两种方式。

1. 动态创建任务

BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,      // 任务函数const char * const pcName,      // 任务名字configSTACK_DEPTH_TYPE usStackDepth, // 栈深度void *pvParameters,             // 任务参数UBaseType_t uxPriority,         // 优先级TaskHandle_t *pxCreatedTask     // 任务句柄
);

参数说明:

参数说明
pvTaskCode任务入口函数
pcName任务名(调试用)
usStackDepth栈大小,以 word 计
pvParameters传入参数
uxPriority优先级(数值越大,优先级越高)
pxCreatedTask任务句柄(可为空)

2. 静态创建任务

xTaskCreateStatic() 需要手动分配堆栈和任务控制块(TCB),常用于安全性要求高的系统:

TaskHandle_t xTaskCreateStatic(TaskFunction_t pvTaskCode,const char * const pcName,uint32_t ulStackDepth,void *pvParameters,UBaseType_t uxPriority,StackType_t *puxStackBuffer,StaticTask_t *pxTaskBuffer
);

静态任务不会依赖 FreeRTOS 的堆管理,更稳定,但更复杂


三、任务的优先级与调度

调度策略

  • 基于优先级:高优先级任务优先运行
  • 同优先级任务:采用时间片轮转

示例

000001002003004LED任务 UART任务 LED任务 UART任务 高优先级任务低优先级任务FreeRTOS 调度示意

四、任务创建实战

示例:两个任务并发

#include "FreeRTOS.h"
#include "task.h"void vTaskLED(void *pvParameters)
{while(1){HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);vTaskDelay(500); // 延时500ms}
}void vTaskUART(void *pvParameters)
{while(1){printf("Hello FreeRTOS!\n");vTaskDelay(1000);}
}int main(void)
{HAL_Init();SystemClock_Config();// 创建两个任务xTaskCreate(vTaskLED, "LED", 128, NULL, 2, NULL);xTaskCreate(vTaskUART, "UART", 128, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();while(1) {}
}

五、任务句柄的使用

获取任务信息

TaskHandle_t xHandleLED, xHandleUART;xTaskCreate(vTaskLED, "LED", 128, NULL, 2, &xHandleLED);
xTaskCreate(vTaskUART, "UART", 128, NULL, 1, &xHandleUART);

任务句柄可用于:

  • 删除任务 vTaskDelete(xHandle)
  • 挂起/恢复任务 vTaskSuspend(xHandle) / vTaskResume(xHandle)
  • 动态修改优先级 vTaskPrioritySet(xHandle, newPriority)

六、任务生命周期

被调度
时间片用完
vTaskDelay / 等待资源
超时/资源可用
创建
就绪
运行
阻塞
删除

七、常见问题与解决方法

问题可能原因解决方法
任务未运行调度器未启动确认 vTaskStartScheduler()
栈溢出栈设置过小增大 usStackDepth
多任务不切换SysTick 中断未配置检查 SysTick_Handler
打印乱码串口任务未同步使用信号量/队列管理输出

八、经验分享

📌 开发建议

  1. 任务数量不要太多,模块化设计 更重要
  2. 建议使用 configCHECK_FOR_STACK_OVERFLOW 开启栈检测
  3. 调试时多用 uxTaskGetStackHighWaterMark() 观察剩余栈空间
  4. 使用 vTaskDelay() 而不是阻塞式 for 循环,保证调度公平

九、总结

通过本章学习,你应该掌握:

  • 使用 xTaskCreate() 创建任务
  • 理解任务的优先级和调度规则
  • 管理任务的生命周期(创建、挂起、恢复、删除)
  • 编写多任务并发程序

至此,你已经能够写出一个 多任务系统,并亲身感受到 RTOS 与裸机的差异。


🔗 FreeRTOS专栏👉 下一章:2025最新超详细FreeRTOS入门教程:第三章 FreeRTOS任务管理 —— 将深入讲解任务的挂起、删除、优先级动态调整等更高级操作。



文章转载自:

http://o9jHsaAt.wqngt.cn
http://yx7fkQBh.wqngt.cn
http://PrgnVmLW.wqngt.cn
http://CZkWtegY.wqngt.cn
http://iwHZWMkM.wqngt.cn
http://P1c5Qv3u.wqngt.cn
http://UiMk5HM0.wqngt.cn
http://1aqHCeMx.wqngt.cn
http://N9fqCkZH.wqngt.cn
http://86cbiQ70.wqngt.cn
http://CX5fKdpR.wqngt.cn
http://GuPky3y7.wqngt.cn
http://Ti0nzuTf.wqngt.cn
http://mjcIsstI.wqngt.cn
http://UuFzdJSV.wqngt.cn
http://MRATXG8l.wqngt.cn
http://vQpEcnjd.wqngt.cn
http://yAS2BFwN.wqngt.cn
http://XF2MJEBj.wqngt.cn
http://CVDPfeMq.wqngt.cn
http://BElSMcju.wqngt.cn
http://RPtsXzG2.wqngt.cn
http://HLOUX3hj.wqngt.cn
http://nfqXEqdL.wqngt.cn
http://xQX1QdZX.wqngt.cn
http://jsEQWiya.wqngt.cn
http://US9DTvsJ.wqngt.cn
http://KNbBxrjO.wqngt.cn
http://TEtRUf2x.wqngt.cn
http://breRExGn.wqngt.cn
http://www.dtcms.com/a/370135.html

相关文章:

  • Webpack热更新(HMR)底层原理详解
  • repo 学习教程
  • 54.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--新增功能--实现手机邮箱注册
  • C/C++内存管理详解:从基础到精通的完整指南
  • 鸿蒙Next开发指南:UIContext接口解析与全屏拉起元服务实战
  • 系统编程day05-进程间通信-信号
  • OpenHarmony之有源NFC-connected_nfc_tag模块详解
  • 吴恩达机器学习合集
  • java基础学习(五):对象中的封装、继承和多态
  • 神马 M66S+ 282T矿机参数详解:SHA-256算法与Hydro冷却技术
  • AI 生成式艺术重塑动漫角色创作:从技术逻辑到多元可能性(一)
  • c++primer 个人学习总结-模板和泛型编程
  • solidity的高阶语法2
  • 9.FusionAccess桌面云
  • SpringBoot集成XXL-JOB保姆教程
  • Linux 网络流量监控 Shell 脚本详解(支持邮件告警)
  • 阿里云对象存储OSS的使用
  • WSL2环境下因服务器重装引发的SSH连接问题排查记录
  • 02-Media-6-rtsp_server.py 使用RTSP服务器流式传输H264和H265编码视频和音频的示例程序
  • I/O 多路复用 (I/O Multiplexing)
  • Nginx性能调优:参数详解与压测对比
  • java接口和抽象类有何区别
  • C/C++动态爱心
  • YOLOv8 在 Intel Mac 上的 Anaconda 一键安装教程
  • 关于 React 19 的四种组件通信方法
  • Joplin-解决 Node.js 中 “digital envelope routines::unsupported“ 错误
  • [论文阅读] 软件工程 - 需求工程 | 2012-2019年移动应用需求工程研究趋势:需求分析成焦点,数据源却藏着大问题?
  • sensitive-word 敏感词性能提升14倍优化全过程 v0.28.0
  • 留数法分解有理分式
  • 基于FPGA的汉明码编解码器系统(论文+源码)