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

FreeRTOS【3-1】创建第一个多任务程序复习笔记

一、整体知识框架与学习目标

本次课程聚焦 FreeRTOS 多任务程序创建,核心是掌握利用 FreeRTOS 接口创建多任务,理解多任务意义、任务句柄概念,通过实操搭建基础多任务应用。后续基于此,可拓展更复杂任务调度、通信等 FreeRTOS 开发。

二、核心概念与需求拆解

(一)多任务的意义

  • 背景:在嵌入式系统中,若仅单任务执行,程序需按顺序依次完成功能,比如先执行 LED 控制,再执行 LCD 显示,无法同时响应多个功能需求 。
  • 价值:多任务能让系统 “并行”(实际是 FreeRTOS 调度的伪并行,基于时间片或优先级切换 )处理不同功能,像同时采集传感器数据、控制设备外设(LED、LCD 等)、处理通信数据,提升系统响应速度与效率,让嵌入式设备功能更丰富、交互更流畅。

(二)任务句柄(TaskHandle_t )

  • 定义:任务句柄是 FreeRTOS 中用于标识和操作任务的一种数据类型 。可把它理解成任务的 “身份证”“把手”,通过句柄能在系统中找到对应任务,进而对任务进行挂起、恢复、删除、查询状态等操作 。
  • 作用:创建任务时,若提供句柄(xTaskCreate 的 pxCreatedTask 参数 ),后续可通过该句柄精准控制任务;即便创建时未主动使用,FreeRTOS 内部也会用它管理任务调度等流程 。

三、分步解析(结合图片与代码 )

(一)目标

  • 内容:需创建两个任务,任务 A 运行 Led_Test 函数,负责 LED 相关功能(比如 LED 闪烁、亮灭控制 );任务 B 运行 LCD_Test 函数,处理 LCD 显示(字符、画面刷新等 ),让 LED 控制和 LCD 显示 “并行” 开展 。

(二)接口函数

  • 函数原型BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
  • 参数解析
    • TaskFunction_t pxTaskCode:任务函数入口,填要运行的任务函数名(如 Led_TestLCD_Test ),告诉系统任务具体执行啥逻辑 。
    • const char * const pcName:任务名称,字符串形式,主要用于调试、查看任务信息,方便识别不同任务 。
    • const configSTACK_DEPTH_TYPE usStackDepth:任务栈深度,为任务运行分配栈空间,存储局部变量、函数调用上下文等,需根据任务复杂度合理设置(如 128,表示栈空间大小 ) 。
    • void * const pvParameters:传给任务函数的参数,若任务函数无需参数,填 NULL ;若需传数据(如给 LCD 任务传显示内容 ),可通过此参数传递 。
    • UBaseType_t uxPriority:任务优先级,数值越大优先级越高,FreeRTOS 依据优先级调度任务,高优先级任务满足条件时会抢占低优先级任务运行 。
    • TaskHandle_t * const pxCreatedTask:任务句柄存储地址,创建任务成功后,句柄值会填充到该指针指向的变量,后续用句柄操作任务 。
  • 位置:在明确目标后,解析创建任务的 “工具”——xTaskCreate 函数,是代码编写的关键依据 。插入第二张图,清晰展示函数原型与参数,辅助理解每个参数干啥用 。

(三)代码示例与关联(对应第三、四、五、六张图 )

1. 任务函数示例(对应第四张图 OLED_Test 、第三张图 MyTask 等 )
  • OLED_Test 函数
    • 代码逻辑:先初始化 OLED(OLED_Init )、清屏(OLED_Clear ),然后进入死循环 while(1) ,循环里不断执行字符打印(OLED_PutChar 打印 'A''Y' )、字符串显示(OLED_PrintString 显示 Hello World! )、数值打印(OLED_PrintSignedVal 显示递增的 cnt ),模拟 LCD/OLED 持续显示刷新的任务逻辑 。可把它类比成 LCD_Test 这类显示任务的实现参考,体现任务函数的一般写法:初始化 + 循环执行功能 。。
  • MyTask 函数
    • 代码逻辑void MyTask(void *argument) 是任务函数模板,argument 用于接收 xTaskCreate 传入的参数(pvParameters ),函数内死循环 while(1) 不断调用 Led_Test ,实现 LED 相关功能持续执行,是任务 A(运行 Led_Test )的一种封装方式 。
2. 任务创建代码
  • 标准创建示例
    • 代码xTaskCreate(MyTask, "myfirsttask", 128, NULL, osPriorityNormal, NULL);
    • 参数解析
      • MyTask:任务函数,即任务要执行的代码逻辑入口 。
      • "myfirsttask":任务名称,调试时便于识别 。
      • 128:栈深度,给任务分配 128 单位栈空间(需根据实际任务复杂度调整,太小可能栈溢出,太大会浪费内存 ) 。
      • NULL:传给任务函数的参数,这里无参数传递 。
      • osPriorityNormal:任务优先级,osPriorityNormal 是系统定义的优先级宏(不同系统可能有差异,FreeRTOS 里对应特定数值 ) 。
      • NULL:任务句柄,这里未使用,传 NULL ,若后续要控制任务,需替换成有效的句柄变量 。
  • xTaskCreate 与 xTaskCreateStatic 对比
    • 代码逻辑:根据 mem 变量值选择创建任务的方式,mem == 1 时用 xTaskCreateStatic(静态创建任务,需提前分配栈和任务控制块内存 );mem == 0 时用 xTaskCreate(动态创建,由 FreeRTOS 管理内存分配 ) 。体现 FreeRTOS 灵活的任务创建方式,动态创建更便捷(无需手动管理内存 ),静态创建在对内存分配有严格控制需求(如内存资源紧张、需确定内存布局 )时使用 。
3. 多任务框架关联
  • 内容:图中展示 osThreadNew 作为中间层,对接不同 RTOS(FreeRTOS、RT-Thread ),调用 osThreadNew 实际会中转到 xTaskCreate(FreeRTOS 场景 )或 rt_thread_create(RT-Thread 场景 ) 。说明在不同 RTOS 封装、中间件环境下,任务创建的 “中转” 逻辑,帮助理解上层接口与 FreeRTOS 底层创建函数的关联,也体现 RTOS 生态里接口封装、适配的思路 。

(四)源码工程

  • 路径DShanMCU-F103开发板资料 > 5_程序源码 > 02_FreeRTOS程序 > 02_视频配套的源码 > 01_freertos_my.7z ,解压后 01_freertos_my 是工程文件夹 。
  • 作用:这是实操的基础,所有代码修改、编译、调试都基于该工程。需把前面解析的任务创建代码(如创建任务 A、任务 B 的 xTaskCreate 调用 )添加到工程合适位置(一般在初始化代码或主任务创建区域 ),编译工程(不同开发环境操作有差异,如 MDK-ARM、GCC 等 ),下载到开发板运行,验证多任务是否按预期执行(LED 功能、LCD 功能同时运行 ) 。

四、完整实操流程梳理(把知识串起来 )

  1. 准备工程:解压 01_freertos_my.7z ,找到工程文件,用对应开发环境(如 Keil MDK 打开 .uvprojx 文件 )加载工程 。
  2. 编写任务函数:定义 Led_Test 和 LCD_Test 函数(参考 OLED_TestMyTask 写法 ),Led_Test 实现 LED 控制逻辑(如循环翻转 LED 引脚电平实现闪烁 ),LCD_Test 实现 LCD 显示逻辑(字符、画面更新 ) 。
  3. 创建任务:在工程初始化代码(如 main 函数、任务创建初始化函数 )里,调用 xTaskCreate 两次,分别创建任务 A(关联 Led_Test )、任务 B(关联 LCD_Test ),设置好任务名称、栈深度、优先级、句柄(按需使用 )等参数 。
  4. 编译下载:编译工程,解决语法错误(如函数未定义、参数不匹配等 ),编译通过后,用调试器或下载工具把程序烧录到 DShanMCU-103 开发板 。
  5. 验证功能:观察开发板运行情况,LED 按 Led_Test 逻辑工作(如规律闪烁 ),LCD 按 LCD_Test 逻辑显示(如字符、画面正常 ),说明多任务创建成功、调度正常 。

五、易错点与补充说明

(一)易错点

  • 栈深度设置:若栈深度过小,任务运行中局部变量多、函数调用层级深时,会栈溢出,导致程序崩溃、行为异常(如任务莫名停止、系统重启 );设置过大,会浪费内存,可能使系统内存不足无法创建其他任务 。需根据任务实际需求,逐步调试、确定合理栈深度(可从经验值如 128、256 等尝试 ) 。
  • 任务函数死循环:任务函数必须是死循环(如 while(1) ),若函数执行完(无循环 ),任务会进入删除状态,无法持续执行功能。编写 Led_TestLCD_Test 时,要确保逻辑在循环里 。
  • 优先级冲突:若多个高优先级任务持续占用 CPU(如死循环里无阻塞操作 ),低优先级任务可能长期无法得到调度,需合理设置优先级,且在任务中适当加入阻塞(如 vTaskDelay ,让 CPU 有机会调度其他任务 ) 。

(二)补充说明

  • FreeRTOS 配置:工程需正确配置 FreeRTOS(如 FreeRTOSConfig.h 里使能任务创建相关宏、设置系统时钟节拍等 ),否则 xTaskCreate 可能无法正常工作 。一般开发板配套 FreeRTOS 工程已做好基础配置,若自定义工程,要仔细核对 。
  • 调试技巧:若任务未按预期运行,可借助开发环境调试功能(如断点调试,查看任务函数是否执行、变量值是否正确 ),或在任务里加入串口打印(如打印调试信息到串口,查看任务执行流程 ),辅助定位问题 。
http://www.dtcms.com/a/338383.html

相关文章:

  • STM32驱动SG90舵机全解析:从PWM原理到多舵机协同控制
  • Sring框架-IOC篇
  • ​​Java核心知识体系与集合扩容机制深度解析​
  • JavaSE高级-02
  • JDBC的使用
  • 【Python】Python Socket 网络编程详解:从基础到实践​
  • Street Crafter 阅读笔记
  • IDEA创建项目
  • MYSQL中读提交的理解
  • MySQL新手教学
  • lesson41:MySQL数据库进阶实战:视图、函数与存储引擎全解析
  • springBoot启动报错问题汇总
  • OVS:ovn是如何支持组播的?
  • LwIP 核心流程总结
  • wishbone总线
  • thinkphp8:一、环境准备
  • c++26新功能—可观测检查点
  • torch.nn.Conv1d详解
  • C++最小生成树
  • 高等数学 8.5 曲面及其方程
  • Python打卡Day45 预训练模型
  • 【加密PMF】psk-pmk-ptk
  • 【168页PPT】IBM五粮液集团数字化转型项目实施方案建议书(附下载方式)
  • 块体不锈钢上的光栅耦合表面等离子体共振的复现
  • 九联科技UMA223-H低功耗蜂窝模组在物联网设备中的应用与价值分析
  • 信号上升时间Tr不为0的信号反射情况
  • 工具集成强化学习:AI数学推理能力的新跃迁
  • Milvus向量数据库安装步骤
  • DRG/DIP支付改革如何通过大数据分析优化病种分组和权重调整?
  • 知识蒸馏 - 各类概率分布