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

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.xdnf.cn/news/19474.html

相关文章:

  • 洛谷 P5836 [USACO19DEC] Milk Visits S-普及/提高-
  • 贪心算法解决钱币找零问题(二)
  • 基于单片机倒车雷达/超声波测距设计
  • Linux->网络入门
  • 《论文阅读》从心到词:通过综合比喻语言和语义上下文信号产生同理心反应 2025 ACL findings
  • infinityfree mysql 加入数据库部分 filezilla 设备共享图片和文本不用浏览器缓存
  • 第六章 Vue3 + Three.js 实现高质量全景图查看器:从基础到优化
  • hive表不显示列注释column comment的问题解决
  • Linux signal 图文详解(二)信号发送
  • 为什么服务器接收 URL 参数时会接收到解码后的参数
  • DHT11-温湿度传感器
  • openEuler2403部署Redis8集群
  • 京东入局外卖,还有很多问题。
  • Ubuntu 服务器实战:Docker 部署 Nextcloud+ZeroTier,打造可远程访问的个人云
  • 学习 Android (十八) 学习 OpenCV (三)
  • OpenHarmony 分布式感知中枢深度拆解:MSDP 框架从 0 到 1 的实战指南
  • 餐饮外卖同城配送酒水寄存餐品加价换购促销小程序APP
  • Windows 安装配置解压版MongoDb
  • TFT屏幕:STM32硬件SPI+DMA+队列自动传输
  • 【RelayMQ】基于 Java 实现轻量级消息队列(五)
  • 2025 最新Vue前端面试题目 (9月最新)
  • AI 重构医疗诊断:影像识别准确率突破 98%,基层医院如何借技术缩小诊疗差距?
  • 设备服务管理上报方案
  • 两轮车车机 OS 演进路线深度解析
  • libmodbus源码分析
  • 【前端】《手把手带你入门前端》前端的一整套从开发到打包流程, 这篇文章都会教会你;什么是vue,Ajax,Nginx,前端三大件?
  • 差角函数差角矩阵位置编码
  • 无需服务器也能建网站:Docsify+cpolar让技术文档分享像写笔记一样简单
  • 手机版碰一碰发视频源码搭建,技术实现与实操指南
  • 鸿蒙开发进阶(HarmonyOS)