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

STM32-FreeRTOS操作系统-任务创建

引言

在当今嵌入式系统开发中,STM32与FreeRTOS的结合应用极为广泛。本文将深入探讨如何在STM32上创建FreeRTOS任务,助力开发者高效构建多任务系统。

搭建Free-RTOS操作系统原因

在嵌入式领域开发中,随着应用复杂度的提升,单线程的程序已难满足需求。STM32作为高性能的微处理器,搭配上FreeRTOS操作系统,能够实现多任务并行处理,有效提升系统的效率及响应速度。我们都知道,我们一般写的程序都是一行一行执行下来,这样程序的利用率不高,而且至始至终只能干一件事,不能同时执行多个程序。我认为这就是裸机开发的最致命的缺点。

任务创建

在任务创建之前,要确保含有该Free-RTOS操作系统的相关文件并且移植到自己的编译器中。

第一步,创建任务句柄

TaskHandle_t MyTaskHandler;//任务句柄

TaskHandle_t是一个类型定义,用于储存任务的句柄,它是一个指向任务控制块(Task Control Block,TCB)的指针。MyTaskHandler是任务句柄,可自定义。

第二步,创建起始任务函数

void Start_Task(void)
{
xTaskCreate(MyTask,"MyTask",128,NULL,1,&MyTaskHandler);//动态方法创建任务
vTaskStartScheduler();//启动任务调动        
}

xTaskCreate是FreeRTOS中用于创建任务的函数,它允许用户在运行时动态创建任务,并将任务的控制信息储存在任务控制块(TCB)中,其函数原型如下:

BaseType_t xTaskCreate(TaskFunction_t pxTaskCode,          // 任务的入口函数,必须是一个无限循环const char * const pcName,          // 任务的名称,用于调试目的const uint16_t usStackDepth,        // 任务堆栈的大小,以字为单位void * const pvParameters,          // 传递给任务函数的参数UBaseType_t uxPriority,             // 任务的优先级TaskHandle_t * const pxCreatedTask  // 任务句柄的指针,用于存储创建的任务的句柄
);

BaseType_t 是FreeRTOS中的一个基本数据类型,在FreeRTOS的相关文件中被定义为typedef long BaseType_t,显然一个32位有符号整数,有些不同版本可能会有不同,感兴趣的可自行查看。它通常被用在函数的返回值中,pdPASS表示成功,pdFALL表示失败。

第三步,启动任务调度器

    vTaskStartScheduler();//启动任务调动        

在调用vTaskStartScheduler()之前,虽然可以创建任务,但该任务不会执行,只有调用该函数后,任务调度器才开始工作。一旦调用该函数,程序的控制权就会交给调度器,调度器会根据任务的优先级和状态来调度任务。(注:vTaskStartScheduler()函数只能被调用一次,如果多次调用,可能会导致错误)。

第四步,主函数调用起始任务函数

int main(void)
{    
KEY_Init();//初始化按键
LED_Init();//初始化LED    
OLED_Init(); //初始化oled屏幕
SysTick_Init(72); //初始化定时器
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
Usart1_Init(115200);//串口初始化
Start_Task();//调用起始任务
while(1);
}

第五步,在起始任务函数中创建任务函数

void MyTask(void *arg)            //开始创建任务函数
{
taskENTER_CRITICAL();           //进入临界区
xTaskCreate(MyTask1,"MyTask1",50,NULL,2,&MyTask1Handler);//动态方法创建任务1

    vTaskDelete(MyTaskHandler);    //删除开始任务
taskEXIT_CRITICAL();                //退出临界区
}

首先,创建任务1也是要先创建任务句柄。其次,使用taskENTER_CRITICAL()进入临界区函数和 taskEXIT_CRITICAL()退出临界区函数,是为了防止在任务创建的过程中被其他任务打断,,确保任务创建成功。

第六步,任务的具体实现

void MyTask1(void *arg)      //任务2函数体
{
while(1)
{
OLED_ShowString(1,1,"Runing Task2");//oled屏幕显示
GPIO_ResetBits(GPIOC,GPIO_Pin_15);//点灯
delay_ms(1000); //程序延迟1s            
GPIO_SetBits(GPIOC,GPIO_Pin_15);//灭灯
vTaskDelay(300); //程序阻塞300ms 
}    
}

重点来说一下delay_ms(1000)函数与vTaskDelay(300)函数,首先要明白一点,STM32单片机使用的FreeRTOS操作系统的时钟通常都是由systick滴答定时器提供的。所以delay_ms()函数它是一个阻塞式延时函数,什么是阻塞式?就是程序在执行期间无法运行其它函数,直到阻塞结束才继续往下运行。而vTaskDelay(),可以说是非阻塞式函数,也可以说是阻塞式函数,当执行到该函数时,该任务会被挂起,转而去执行次优先级的任务函数。它只是阻塞当前的任务,而不会阻塞整个系统。

七,完整示例代码

首先在main.c中调用起始任务函数

#include "myfreertos.h"
#include "stm32f10x.h"   // Device header
#include "SysTick.h"
#include "Usart.h"
#include "oled.h"
#include "led.h"
#include "key.h"int main(void)
{	KEY_Init();//初始化按键LED_Init();//初始化LED	OLED_Init(); //初始化oled屏幕SysTick_Init(72); //初始化定时器NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4Usart1_Init(115200);Start_Task();//调用任务while(1);
}

在myfreetros.c中实现具体任务

#include "myfreertos.h"
#include "FreeRTOS.h"
#include "SysTick.h"
#include "Usart.h"
#include "oled.h"
#include "Task.h"
#include "led.h"
#include "key.h"TaskHandle_t MyTaskHandler;//任务句柄TaskHandle_t MyTask1Handler;//任务1句柄void MyTask(void *pvParameters);    //声明启动函数void Start_Task(void)
{xTaskCreate(MyTask,"MyTask",128,NULL,1,&MyTaskHandler);//动态方法创建任务vTaskStartScheduler();//启动任务调动		
}void MyTask(void *arg)            //开始创建任务函数
{taskENTER_CRITICAL();           //进入临界区xTaskCreate(MyTask1,"MyTask1",50,NULL,2,&MyTask1Handler);//动态方法创建任务1vTaskDelete(MyTaskHandler);    //删除开始任务taskEXIT_CRITICAL();           //退出临界区
}void MyTask1(void *arg)     //任务1函数体
{	while(1){OLED_ShowString(1,1,"Runing Task1");GPIO_ResetBits(GPIOC,GPIO_Pin_13);vTaskDelay(300);GPIO_SetBits(GPIOC,GPIO_Pin_13);vTaskDelay(900);}	
}

总结

本文简单介绍了在STM32微控制器上使用FreeRTOS操作系统创建任务的方法,包括任务函数定义、任务创建函数调用及任务优先级设置等内容,帮助开发者快速掌握STM32下FreeRTOS任务创建的关键步骤。

http://www.dtcms.com/a/360939.html

相关文章:

  • 开源AI大模型AI智能名片S2B2C商城小程序赋能下的“信息找人“:人工智能驱动的线下零售精准化革命
  • 高效大规模创新3D重建模型iLRM
  • 【STM32】贪吃蛇 [阶段 3] 增强模块结构(架构优化)
  • HarmonyOS应用开发深度解析:基于Stage模型与ArkTS的现代实践
  • ServBay 是一款集成式、图形化的本地 Web 开发环境工具,专为 macOS 和 Windows 系统设计
  • LeetCode 142. 环形链表 II - 最优雅解法详解
  • Linux自动化构建工具-make/Makefile
  • 【并发场景问题】超卖、一人一单业务问题的解决方案
  • AI 重构医疗诊断:影像识别准确率突破 98%,基层医院如何借技术缩小诊疗差距?
  • Git指令 | 个人学习笔记
  • Interceptor拦截器入门知识及其工作原理
  • Python OpenCV图像处理与深度学习:Python OpenCV图像滤波入门
  • gradle安装、配置环境变量、配置阿里源及idea 中配置gradle
  • RabbitMinQ(模拟实现消息队列项目)02
  • Axure科技感可视化原型案例:赋能设计与研发的宝藏资源
  • 二、感知机
  • 你的Redis是不是在家能用,到了学校就连不上?
  • CPTS-Vintage 票据,基于资源的约束委派 (RBCD),DPAPI密钥
  • 搭建APP应用程序如何选择服务器
  • ‌NAT穿透技术原理:P2P通信中的打洞机制解析‌
  • 【机器学习入门】4.4 聚类的应用——从西瓜分类到防控,看无监督学习如何落地
  • Windows11安装WSL教程
  • HBase实战(一)
  • golang json v1 和 v2对比差异
  • 【重学MySQL】九十六、MySQL SQL Mode高效配置全攻略
  • Beego: Go Web Framework 详细指南
  • ⚡ Linux xargs 命令参数详解
  • 【数据可视化-103】蜜雪冰城门店分布大揭秘:2025年8月数据分析及可视化
  • Ubuntu 25.10 Snapshot4 发布。
  • 小迪Web自用笔记23