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

FreeRTOS学习笔记(二)

FreeRTOS学习笔记(二)

在STM32F407ZGT6上实现任务创建和删除

前言

  • 为什么要引入操作系统?

在没有操作系统之前,编写程序一直使用大while循环的方式来完成检查,然后使用中断的方式进行异常处理。然而当任务增多时,很难保证高优先级任务(如紧急报警)能够及时响应。

并且随着单片机处理的工作增多,while大循环中的控制逻辑越来越复杂,到了最后连编写程序的本人也无法修改,最后形成了一座shit山。

为了解耦不同功能的程序和保证工作完成的实时性,引入了操作系统,例如freeRTOS。而引入嵌入式操作系统本质上是用“空间换时间”和“用架构换效率”。

  • 操作系统如何工作?

FreeRTOS 作为一个轻量级的实时操作系统(RTOS),其核心工作机制是围绕任务调度和系统时钟节拍展开的。本篇学习笔记主要围绕任务基础(创建和删除)展开。

  • 什么是任务?

简要来说,任务可以理解为一段拥有自己独立执行环境和上下文的程序代码。打个比方来说,如果把 单片机 比作一个厨师,那么“任务”就是厨师手里正在做的一道道菜。厨师同一时间只能炒一道菜(单核),但他可以迅速切换去处理另一道即将出锅的菜(任务切换),在宏观上看起来就像是同时在做很多道菜一样。

​ 开始烧菜时总要先开火,菜出锅总要把装盘。在FreeRTOS 中任务的创建和删除就好比开火和装盘。

  • 用动态内存分配方法创建任务

下面给出一个实例是在之前已经移植了freeRTOS的基础工程上创建两个任务,LED0是每秒闪烁1次;LED1是每秒闪烁2次。LED0闪烁10次后将LED任务删除,让LED1不再闪烁。

具体代码如下:

1.创建任务函数

/* Led0Task 任务 配置 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 */staticvoidLed0Task(void*pvParameters);/* 任务函数 */staticTaskHandle_t Led0TaskHandle=NULL;/* 任务句柄 */#defineLed0Task_PRIO4/* 任务优先级 */#defineLed0Task_STK_SIZE128/* 任务堆栈大小 *//* Led1Task 任务 配置 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 */staticvoidLed1Task(void*pvParameters);/* 任务函数 */staticTaskHandle_t Led1TaskHandle=NULL;/* 任务句柄 */#defineLed1Task_PRIO4/* 任务优先级 */#defineLed1Task_STK_SIZE128/* 任务堆栈大小 *//** * @brief Led1Task * @param pvParameters : 传入参数 * @retval 无 */staticvoidLed1Task(void*pvParameters){while(1){LED1_TOGGLE();vTaskDelay(pdMS_TO_TICKS(250));printf("LED1正在以0.5秒周期闪烁\r\n");}}

2.定义任务句柄,用vTaskCreate()创建任务

/** * @brief appStartTask * @param 无 * @retval 无 */voidappStartTask(void){taskENTER_CRITICAL();/*进入临界段,关中断*/xTaskCreate((TaskFunction_t)Led0Task,/* 任务函数 */(constchar*)"Led0Task",/* 任务名称 */(uint16_t)Led0Task_STK_SIZE,/* 任务堆栈大小 */(void*)NULL,/* 传入给任务函数的参数 */(UBaseType_t)Led0Task_PRIO,/* 任务优先级 */(TaskHandle_t*)&Led0TaskHandle);/* 任务句柄 */xTaskCreate((TaskFunction_t)Led1Task,/* 任务函数 */(constchar*)"Led1Task",/* 任务名称 */(uint16_t)Led1Task_STK_SIZE,/* 任务堆栈大小 */(void*)NULL,/* 传入给任务函数的参数 */(UBaseType_t)Led1Task_PRIO,/* 任务优先级 */(TaskHandle_t*)&Led1TaskHandle);/* 任务句柄 */taskEXIT_CRITICAL();/*退出临界段,开中断*/vTaskStartScheduler();/*开启任务调度器*/}

3.用vTaskDelete函数释放内存

/** * @brief Led0Task * @param pvParameters : 传入参数 * @retval 无 */staticvoidLed0Task(void*pvParameters){uint16_tcnt=0;while(1){LED0_TOGGLE();vTaskDelay(pdMS_TO_TICKS(500));printf("LED0正在以1.0秒周期闪烁\r\n");if(++cnt>=10){if(eTaskGetState(Led1TaskHandle)!=eDeleted)/*如果没有被删除*/{vTaskDelete(Led1TaskHandle);/*删除LED1闪烁任务*/printf("LED1任务已经被删除\r\n");}}}vTaskDelete(NULL);}

main函数

/* USER CODE BEGIN Includes */#include"led.h"#include"freertos.h"#include"task.h"#include<stdio.h>#include"freertos_demo.h"/* USER CODE END Includes */***@brief The application entry point.*@retvalint*/intmain(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */led_init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */appStartTask();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}

运行结果

/* Infinite loop/
/
USER CODE BEGIN WHILE/
while (1)
{
/
USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */
}

运行结果 ![任务创建和删除](https://i-blog.csdnimg.cn/direct/18849ae17f874ba99b5b909ea701772c.jpeg#pic_center)
http://www.jsqmd.com/news/1099727/

相关文章:

  • [对比学习LangChain和MAF-16]基于Checkpoint的持久化
  • C中单向链表之增删改查
  • 导入Seata-server所需SQL
  • 四川大学《微积分I-1》期末试卷及答案2016-2025学年PDF
  • OpenHarness源码研究-5-基础设施
  • 什么是配置中心?有哪些常见的配置中心?
  • 【车载 AOSP 16 蓝牙(bluedroid)服务】【qcom 平台双蓝牙】【13.耳机如何协商采样率:从 AVDTP 到 AAC 44100 的一条路】
  • 第六周学习报告
  • 我做了一个基于心理测评和场景记忆的 AI 伴侣产品 CandyAI
  • 爆品之后:新消费品牌如何用数字化穿越增长瓶颈?
  • YOLO目标检测论文实战指南:从模型改进到实验写作全流程
  • 2.1.8 this指针
  • 免费开源NoFences桌面分区管理工具:3步打造高效整洁Windows桌面
  • Day10 | SFT 训练实操——用 QLoRA 微调 Qwen3-8B
  • BetterJoy完整指南:让Switch手柄在PC游戏上完美运行
  • 智谱大模型LLM一面,人麻了!!!
  • 【JAVA毕设源码分享】基于springboot的小区公共收益管理系统 的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 光电经纬仪测量中的坐标系体系及其应用
  • CPT Markets:把外汇用户支持体系做到位——维度复盘与提示整理
  • 抖音内容批量采集与智能管理工具:从零到精通的完整指南
  • OpenAI / Claude API 报错 401、403、429 怎么解决?一文讲清 API Key 失效排查思路
  • 量子虚时演化算法原理与sine-Gordon模型模拟实践
  • FreeCAD源码分析: Property View
  • 我一个人 11 天交付了两个模块——不是会分身,是让两个 AI 打了配合
  • 1115.交替打印FooBar
  • 【课程设计/毕业设计】基于 SpringBoot 的农业设备销售订单管理系统的设计与实现 基于 SpringBoot 的智慧农机综合服务管理系统【附源码、数据库、万字文档】
  • 修改很简单,但网上讲这点的文档不多,因此多记一笔。另外基于out_ptr会临时转移所有权这点来看,共享所有权模型的std::shared_ptr其实并不适合使用out_ptr,虽然标准没有禁止甚至还要
  • playwright-拖拽验证码
  • LeWorldModel:基于JEPA的轻量化世界模型实践指南
  • 为什么要将 RTF 转换为 PDF?