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

【STM32项目】在FreeRtos背景下的实战项目的实现过程(一)

在这里插入图片描述
个人主页~

这篇文章是我亲身经历的,在做完一个项目之后总结的经验,虽然我没有将整个项目给放出来,因为这项目确实也是花了米让导师指导的,但是这个过程对于STM32的实战项目开发都是非常好用的,可以说按照这个过程,在你熟悉各种外设的前提下,你可以不用受别人指导地进行一个项目,甚至完成自己的一个作品


实战项目的实现过程

  • 一、FreeRtos
    • 1、简介
    • 2、功能
      • (1)裸机开发
      • (2)基于Rtos的开发
    • 3、格式
      • (1)定义任务
      • (2)定义空闲任务
      • (3)main函数
      • (4)开始任务函数

一、FreeRtos

1、简介

Rtos就是实时操作系统,os的意思就像是我们常用的iOS、HamonyOS是一个意思,就是操作系统的意思,而FreeRtos就是免费的实时操作系统,在嵌入式系统中非常常用

它的底层代码是用C语言写成的,可移植性特别好,且简单易用,核心代码有9000多行

2、功能

(1)裸机开发

像STM32在开始学习的时候,我们的程序是一个main函数,里面的代码一行接着一行执行,非常单一,只要写好程序,程序就会按照既定的顺序执行,不会出现某一段代码先于前面几行的代码的情况,也就是实时性差,这叫做裸机开发也就是不带操作系统的开发,它常用于不需要高实时性的场景的产品开发

在delay函数下的等待只能等待,没有占用CPU的情况,浪费资源

(2)基于Rtos的开发

Rtos有很多种,除了FreeRtos以外,我们可以在浏览器上搜索其他的Rtos,但在所有嵌入式系统中,FreeRtos是应用最多的

添加了Rtos的嵌入式系统实时性会提高,我们可以将某些程序分为多个任务,给予它们优先级,优先级高的优先获得CPU使用权,也就是一个优先级低的任务执行过程中,优先级高的任务一旦出现需要执行的情况,优先级低的任务立刻发生中断,先让优先级高的任务完成,然后再回到原来的位置继续执行,而且这个过程是可以嵌套的,在优先级1的任务过程中,优先级2的任务可以中断优先级1的任务,然后优先级3的任务又可以中断优先级2的任务

多个任务可以同一优先级,创建的实时任务数量没有软件限制,也就是说,在理想条件下,创建的实时任务可以有无数个

在不断中断的过程中,嵌入式系统捕捉外界变化的能力变得十分灵敏,实时性有所提高

在delay函数下按照优先级的顺序使用CPU,确保CPU能在每个时间段都有事情可做,节省资源

3、格式

FreeRtos的配置过程可以直接看正点原子的视频教程,这里其实只要懂得基本原理即可,直接找一个现成的文件用就可以,实在想要自己做就跟着视频教程一步一步来搭建一个Rtos系统
在这里插入图片描述
我们这里就不讲怎么配置了,文本解释不清还占用篇幅

(1)定义任务

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小
#define START_STK_SIZE 		128  
//任务堆栈
StackType_t StartTaskStack[START_STK_SIZE];
//任务控制块
StaticTask_t StartTaskTCB;
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_TASK_PRIO		2
//任务堆栈大小
#define TASK1_STK_SIZE 		128  
//任务堆栈
StackType_t Task1TaskStack[TASK1_STK_SIZE];
//任务控制块
StaticTask_t Task1TaskTCB;
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);//任务优先级
#define TASK2_TASK_PRIO		3
//任务堆栈大小
#define TASK2_STK_SIZE 		128  
//任务堆栈
StackType_t Task2TaskStack[TASK2_STK_SIZE];
//任务控制块
StaticTask_t Task2TaskTCB;
//任务句柄
TaskHandle_t Task2Task_Handler;
//任务函数
void task2_task(void *pvParameters);

开始任务start_task是必须要有的,然后按照一样的格式将任务1234等创建好,确定堆栈以及堆栈大小,控制块、句柄以及任务函数的声明

(2)定义空闲任务

//空闲任务堆栈
static StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
//定时器任务堆栈
static StackType_t Timer_Task_Stack[configTIMER_TASK_STACK_DEPTH];//空闲任务控制块
static StaticTask_t Idle_Task_TCB;	
//定时器任务控制块
static StaticTask_t Timer_Task_TCB;//获取空闲任务的任务堆栈和任务控制块内存,因为本例程使用的是静态内存
//因此空闲任务的任务堆栈由用户来提供,接口函数就是下面这个函数//ppxIdleTaskTCBBuffer:任务控制块内存
//ppxIdleTaskStackBuffer:任务堆栈内存
//pulIdleTaskStackSize:任务堆栈大小
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{*ppxIdleTaskTCBBuffer=&Idle_Task_TCB;*ppxIdleTaskStackBuffer=Idle_Task_Stack;*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}//获取定时器任务的任务堆栈和任务控制块内存
//ppxTimerTaskTCBBuffer:任务控制块内存
//ppxTimerTaskStackBuffer:任务堆栈内存
//pulTimerTaskStackSize:任务堆栈大小void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t**ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize)
{*ppxTimerTaskTCBBuffer=&Timer_Task_TCB;*ppxTimerTaskStackBuffer=Timer_Task_Stack;*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}

在这里插入图片描述

(3)main函数

int main()
{//在前面这里放所使用模块的初始化,将所有用到的外设驱动起来//下面就是开始任务函数的定义StartTask_Handler=xTaskCreateStatic((TaskFunction_t	)start_task,//任务函数		(const char* 	)"start_task",//任务名称		(uint32_t 		)START_STK_SIZE,	//任务堆栈大小(void* 		  	)NULL,		//传递给任务函数的参数		(UBaseType_t 	)START_TASK_PRIO, //任务优先级	(StackType_t*   )StartTaskStack,	//任务堆栈(StaticTask_t*  )&StartTaskTCB);	         //任务控制块vTaskStartScheduler();//开启任务调度
}

在这里插入图片描述

(4)开始任务函数

在FreeRtos进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断
一般我们都会使用这个临界区,进入和退出是配套使用的,我们在使用的时候要尽量保持临时段耗时短

//开始任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();         //进入临界区//创建task1任务Task1Task_Handler=xTaskCreateStatic((TaskFunction_t	)task1_task,		(const char* 	)"task1_task",		(uint32_t 		)TASK1_STK_SIZE,	(void* 		  	)NULL,				(UBaseType_t 	)TASK1_TASK_PRIO, 	(StackType_t*   )Task1TaskStack,	(StaticTask_t*  )&Task1TaskTCB);	//创建task2任务Task2Task_Handler=xTaskCreateStatic((TaskFunction_t	)task2_task,		(const char* 	)"task2_task",		(uint32_t 		)TASK2_STK_SIZE,	(void* 		  	)NULL,				(UBaseType_t 	)TASK2_TASK_PRIO, 	(StackType_t*   )Task2TaskStack,	(StaticTask_t*  )&Task2TaskTCB);vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}

在这里插入图片描述
这里只是简单地使用FreeRtos,掌握Rtos下的多任务多优先级的实现方式,掌握FreeRtos的基本用法,打造一个实时性系统


今日分享就到这里~

在这里插入图片描述

相关文章:

【STM32项目】在FreeRtos背景下的实战项目的实现过程(一)

个人主页~ 这篇文章是我亲身经历的,在做完一个项目之后总结的经验,虽然我没有将整个项目给放出来,因为这项目确实也是花了米让导师指导的,但是这个过程对于STM32的实战项目开发都是非常好用的,可以说按照这个过程&…...

C#垃圾处理机制相关笔记

C#编程中的垃圾处理机制主要通过垃圾回收器(Garbage Collector,GC)实现自动内存管理。C#作为一种托管语言,其垃圾处理机制显著减轻了程序员的内存管理负担,与C语言等非托管语言形成鲜明对比。具体介绍如下:…...

C语言memcmp函数

目录 开头1.什么是memcmp函数?2.memcmp函数的内部程序流程图 3.memcmp函数的实际应用比较整型数组比较短整型二维数组比较结构体变量…… 结尾 开头 大家好,我叫这是我58。今天,我们要学一下关于C语言里的memcmp函数的一些知识。 1.什么是memcmp函数?…...

低代码: 组件库测试之Vue环境下的测试工具以及测试环境搭建

Vue Test Utils Vue Test Utils 1 targets Vue 2. Vue Test Utils 2 targets Vue 3. 特别注意要使用 版本 2.0.0 以上 提供特定的方法,在隔离的话环境下,进行组件的挂载,以及一系列的测试 配置开发环境 手动配置, 是比较麻烦的vue cli 是基于插件架构的, 插件可以: 安装对…...

【Vue3】高颜值后台管理模板推荐

ELP - 权限管理系统 基于Vue 3框架与PrimeVue UI组件库技术精心构建的高颜值后台权限管理系统模板。该模板系统已成功实现基于RBAC(Role-Based Access Control)模型的权限管理系统和字典数据管理模块,后端则使用了Spring Boot框架&#xff0…...

详细介绍Pytorch中torchvision的相关使用

torchvision 是 PyTorch 的一个官方库,主要用于处理计算机视觉任务。提供了许多常用的数据集、模型架构、图像转换等功能,使得计算机视觉任务的开发变得更加高效和便捷。以下是对 torchvision 主要功能的详细介绍: 1. 数据集(Dat…...

AI部署——主流模型推理部署框架

我们以最经典的Yolov5目标检测网络为例解释一下10种主流推理部署框架的大概内容,省略模型训练的过程,只讨论模型转换、环境配置、推理部署等步骤。 Intel的OpenVINO — CPUNvidia的TensorRT — GPU/CPUOpenCV DNN Module — GPU/CPUMicrosoft ONNX Runti…...

PyTorch之loading fbgemm.dll异常的解决办法

前言 PyTorch是一个深度学习框架,当我们在本地调试大模型时,可能会选用并安装它,目前已更新至2.4版本。 一、安装必备 1. window 学习或开发阶段,我们通常在window环境下进行,因此需满足以下条件: Windo…...

Vscode——如何实现 Ctrl+鼠标左键 跳转函数内部的方法

一、对于Python代码 安装python插件即可实现 二、对于C/C代码 安装C/C插件即可实现...

力扣热题100_回溯_78_子集

文章目录 题目链接解题思路解题代码 题目链接 78. 子集 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入&#xff…...

浏览器如何工作(一)进程架构

分享cosine 大佬,版权©️大佬所有 浏览器的核心功能 浏览器,“浏览” 是这个产品的核心,浏览无非分为两步: 获取想浏览的资源 展示得到的资源 现代浏览器还增加了交互功能,这涉及到脚本运行。因此&#xff0c…...

【LeetCode】两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…...

UE5学习笔记11-为拿取武器添加动画

一、一点说明 动画实例通过扩展为所有机器上的每个字符都存在动画蓝图,动画实例只能访问该计算机上的变量。 二、思路 我在武器组件中有一个武器类的指针,判断当前指针是否为空去判断当前角色是否装备武器 三、实现 1.在角色C类中添加是否装备武器的函…...

68. 文本左右对齐【 力扣(LeetCode) 】

一、题目描述 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。 你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单…...

【中等】 猿人学web第一届 第6题 js混淆-回溯

文章目录 请求流程请求参数 加密参数定位r() 方法z() 方法 加密参数还原JJENCOde js代码加密环境检测_n("jsencrypt")12345 计算全部中奖的总金额请求代码注意 请求流程 请求参数 打开 调试工具,查看数据接口 https://match.yuanrenxue.cn/api/match/6 请…...

低、中、高频率段具体在不同应用中的范围是多少

1、低频率段(Low Frequency Range) ①建筑声学和噪声控制:通常将20 Hz 到 200 Hz 的频率范围视为低频段。在这一范围内,声音的波长较长,通常与低音(如重低音音乐)和建筑结构中的振动有关。 ②…...

Oxford Model600 Model400低温氦压缩机cryogenic helium compressor手侧

Oxford Model600 Model400低温氦压缩机cryogenic helium compressor手侧...

Golang面试题四(并发编程)

目录 1.Go常见的并发模型 2.哪些方法安全读写共享变量 3.如何排查数据竞争问题 ​4.Go有哪些同步原语 1. Mutex (互斥锁) 2. RWMutex (读写互斥锁) 3. Atomic 3.1.使用场景 3.2.整型操作 3.3.指针操作 3.4.使用示例 4. Channel 使用场景 使用示例 5. sync.WaitGr…...

计算机学生高效记录并整理编程学习笔记的方法

哪些知识点需要做笔记? 以下是我认为计算机学生大学四年可以积累的笔记。 ① 编程语言类(C语言CJava):保留课堂笔记中可运行的代码部分,课后debug跑一跑。学习语言初期应该多写代码(从仿写到自己写&#…...

【书生大模型实战】L2-LMDeploy 量化部署实践闯关任务

一、关卡任务 基础任务(完成此任务即完成闯关) 使用结合W4A16量化与kv cache量化的internlm2_5-7b-chat模型封装本地API并与大模型进行一次对话,作业截图需包括显存占用情况与大模型回复,参考4.1 API开发(优秀学员必做)使用Func…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...