STM32(F103ZET6)第二十课:FreeRtos操作系统的应用

news2024/12/24 7:36:22

目录

  • 调试方式
  • 一、任务堆栈溢出检测
  • 二、任务管理方式
  • 三、二值信号量(任务同步)
  • 四、计数信号量
  • 五、互斥信号量
  • 六、队列

调试方式

问题:传感器数据获取问题,有的DHT11能获取到,有的获取不到
两种方式:调优先级或者进临界区,临界区有关中断的机制,保护程序不被打断。
在这里插入图片描述

一、任务堆栈溢出检测

任务空间检测函数:
使用时先开宏定义
在这里插入图片描述
在这里插入图片描述
然后在主函数下面加一个栈溢出钩子函数。当栈溢出时卡死到钩子函数中。
在这里插入图片描述
本质上就是一个钩子函数,在任务上下文切换的时候做检测,具有一定的滞后性,需要在任务发生上下文切换时才会进行,任务堆栈溢出时并不能马上检测到问题。
但大多常见情况下这种检测机制依然是非常实用的功能,可以帮助用户减少代码中的错误并提高应用程序代码的质量。

二、任务管理方式

在这里插入图片描述
1、任务创建完成都处于就绪链表,然后启动调度器后,根据优先级去查找就绪链表里优先级最高的任务,然后去执行,优先级一样的按照创建的顺序执行。
2、执行的任务会变成运行态,从就绪链表中删除,然后任务执行的vTaskDelay等函数时,会被加入到阻塞链表里,调度器选择其他任务去执行。
3、当阻塞解除时,任务重新被添加到就绪链表里,等待调度器调度。如果解除阻塞的任务优先级最高,会立即抢占CPU去执行。

启动调度器的流程:
1,创建空闲任务
2,判断是否使用软件定时器,会创建一个软件定时器的任务
3,关闭中断
4,对操作系统的状态付初值
5,启动调度器:通过汇编的的方式,开启中断,开启第一个任务
任务创建的流程:
每个任务都会有一个任务控制块的结构体,里边保存着任务的相关信息
在这里插入图片描述
1,申请任务栈空间
2,申请任务控制块空间
3,将任务空间地址,赋值给任务控制块TCB的栈指针参数
在这里插入图片描述
4,根据参数去对任务控制块初始化
5,添加任务控制块到就绪链表

三、二值信号量(任务同步)

先创建信号量,然后一个任务给出信号量,一个任务获取信号量
任务B需要等待任务A执行完再去执行,这就叫任务同步。
1、添加头文件

#include "semphr.h"

2、创建信号量
先创建一个信号量句柄:SemaphoreHandle_t Binary;
之后创建一个二值信号量
Binary = xSemaphoreCreateBinary();
3、给出信号量函数
在这里插入图片描述
4获取信号量函数
在这里插入图片描述
测试代码:当按下按键3之后灯任务获取信号量,灯变亮,如果不按下则灯无变化,一直阻塞。

//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{
	uint8_t i=0;
	while(1)
	{
		if(xSemaphoreTake(Binary,1000) == pdTRUE) 
		{
			printf("按键按下,获取到信号量\r\n");
		}else
		{
			printf("获取到信号量等待超时\r\n");
		}
		i++;
		printf("i=%d\r\n",i);
		Led_Toggle(1);
		//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//		Delay_nms(200);//也能延时,但是会一直占用CPU
		//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态
		vTaskDelay(200);
	}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{
	while(1)
	{
		switch(key_getvalue())
		{
			case 1:vTaskSuspend(LED_TaskHandle);break;
			case 2:vTaskResume(LED_TaskHandle);break;
			case 3:xSemaphoreGive(Binary);break;
			case 4:break;
		}
		vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态
	}
}	

四、计数信号量

任务阻塞时,是不会在运行的,什么时候再解除阻塞,是有调度去做的,调度器回去判断某个任务是否具备解除阻塞的条件,如果具备,会将该任务从阻塞链表,放到就绪链表里。一般在资源有限的情况下使用的。

使用之前先创建一个计数信号量句柄:SemaphoreHandle_t Count_Handle;//计数信号量句柄
之后创建一个计数信号量
Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量
其中参数为最大信号量为多少和初始信号量有几个。

由按键给一个信号量xSemaphoreGive(Count_Handle);
灯任务去接受:if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE)

计数信号量测试:按键和灯,按键按下几次,闪烁几次

//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{
	uint8_t i=0;
	while(1)
	{
		if(xSemaphoreTake(Count,portMAX_DELAY) == pdTRUE) 
		{
			printf("按键按下,获取到信号量\r\n");
		}else
		{
			printf("获取到信号量等待超时\r\n");
		}
		i++;
		printf("i=%d\r\n",i);
		Led_Toggle(1);
		//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//	Delay_nms(200);//也能延时,但是会一直占用CPU
		//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态
		vTaskDelay(1000);
	}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{
	while(1)
	{
		switch(key_getvalue())
		{
			case 1:vTaskSuspend(LED_TaskHandle);break;
			case 2:vTaskResume(LED_TaskHandle);break;
			case 3:xSemaphoreGive(Count);break;
			case 4:xSemaphoreGive(Count);break;
		}
		vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态
	}
}	

五、互斥信号量

在这里插入图片描述
互斥的含义:一个资源在使用时,就不能被其他任务再使用了
先创建,和二值信号量不同的是互斥量创建之初里边就有这个信号量,可以被获取到。互斥信号量有借有还。
互斥锁用于共享资源的保护
资源A是共享资源,此时如果被任务B使用,那么就不能被其他任务使用。
先创建一个互斥信号量的句柄:SemaphoreHandle_t Mutex;
之后创建互斥信号量:Mutex = xSemaphoreCreateMutex();
测试printf的保护
void MyPrintf(char *p)
{
xSemaphoreTake(Mutex,portMAX_DELAY);
printf(“%s”,p);
xSemaphoreGive(Mutex);
}
xSemaphoreTake(Mutex,portMAX_DELAY);获取信号量
xSemaphoreGive(Mutex);还回去

优先级继承机制说明:
在这里插入图片描述
优先级反转的情况:M任务先于H任务执行
在这里插入图片描述
使用互斥信号量的情况下:当高优先级任务获取信号量时,会临时将L任务的优先级提高到和他同一等级,等到任务L释放信号量时,优先级恢复为初始状态。避免M任务时间过长,导致H任务要等到M任务执行之后才能运行。
在这里插入图片描述

六、队列

在这里插入图片描述
在这里插入图片描述
创建队列:
在这里插入图片描述
先创建一个队列句柄:QueueHandle_t Queue;
之后创建一个队列:Queue = xQueueCreate(10,2);创建队列 长度为10 ,队列中每个数据的大小2字节
队列发送函数:
在这里插入图片描述

if(xQueueSend(Queue,buff,100) == pdTRUE)
				{
					printf("发送成功\r\n");
				}else
				{
					printf("队列已满,发送失败\r\n");
				}

队列接受函数:
在这里插入图片描述
if(xQueueReceive(Queue,buff2,100)==pdTRUE)
{
printf(“接受数据:%x %x\r\n”,buff2[0],buff2[1]);
}else
{
printf(“队列为空,接收失败\r\n”);
}
代码:

//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{
	uint8_t buff[2] = {0xAA,0x55};
	uint8_t buff2[2] = {0};
	MyPrintf("KEY_Task Begin\r\n");
	while(1)
	{
		switch(key_getvalue())
		{
			case 1:
				if(xQueueSend(Queue,buff,100) == pdTRUE)
				{
					printf("发送成功\r\n");
				}else
				{
					printf("队列已满,发送失败\r\n");
				}
				break;
			case 2:
				if(xQueueReceive(Queue,buff2,100)==pdTRUE)
				{
					printf("接受数据:%x %x\r\n",buff2[0],buff2[1]);
				}else
				{
					printf("队列为空,接收失败\r\n");
				}
				break;
			case 3:xSemaphoreGive(Count);break;
			case 4: break;
		}
		vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态
	}
}	

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2085674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker原理及实例

目录 一 Docker简介及部署方法 1.1 Docker简介 1.1.1 什么是docker? 1.1.2 docker在企业中的应用场景 1.1.3 docker与虚拟化的对比 1.1.4 docker的优势 2 部署docker 2.1 容器工作方法 2.2 部署第一个容器 2.2.1 配置软件仓库 2.2.2 安装docker-ce并启动服…

排序算法见解(2)

1.快速排序 1.1基本思想: 快速排序是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以…

如何构建Java SpringBoot文献检索系统:高效管理学术资料,掌握数据库核心技术

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

搭上“跨境电商”便车,中国家居在海外越杀越勇

文|新熔财经 作者|楷楷 从去年至今,已有多家跨境家居企业谋求IPO,包括近期启动IPO辅导的圣奥科技;今年4月正式向港交所递交招股说明书的傲基科技;去年11月启动A股IPO的跨境家居品牌杰西亚,还有…

vulhub xxe靶机通关教程

首先我们进行端口扫描 扫出来端口之后去尝试得出地址为183 发现robots.txt文件 由此我们就得到了两个目录 我们先进入xxe目录&#xff0c;并开始登录抓包 并进入重放器在xml里面构造语句 <!DOCTYPE r [ <!ELEMENT r ANY > <!ENTITY admin SYSTEM "php://filt…

【在Linux世界中追寻伟大的One Piece】传输层协议UDP

目录 1 -> 传输层 2 -> 端口号 2.1 -> 端口号范围划分 2.2 -> 知名端口号 3 -> UDP协议 3.1 -> UDP协议端格式 3.2 -> UDP的特点 3.2.1 -> 面向数据报 3.3 -> UDP的缓冲区 3.4 -> UDP使用注意事项 3.5 -> 基于UDP的应用层协议 1 -…

Vue实战:轻松掌握输入框@功能实现技巧

成员列表 创建 实现成员列表的方式比较简单&#xff0c;其实就是一个列表&#xff0c;一个简单的v-for循环就可以搞定&#xff0c;点击时将当前选择的成员项回调给父组件。 新增一个AtPop.vue文件&#xff1a; <template> <div class"at-pop-index">…

DIFFUSION 系列笔记| Latent Diffusion Model、Stable Diffusion基础概念、数学原理、代码分析、案例展示

目录 Latent Diffusion Model LDM 主要思想 LDM使用示例 LDM Pipeline LDM 中的 UNET 准备时间步 time steps 预处理阶段 pre-process 下采样过程 down sampling 中间处理 mid processing 上采样 upsampling 后处理 post-process LDM Super Resolution Pipeline…

海康视觉二次开发学习笔记8-从回调函数获取结果

回调函数使用方法 通常在方案或流程执行完成后,就可以获取到流程运行的结果.运行一次流程后,我们就可以获取到流程的渲染结果以及流程的数据结果.那么使用通讯或硬件进行外部触发时,如何获取结果呢? 这种时候就要用到回调函数. 1. 注释原获取结果代码 2. 注册回调函数 在构…

【文献及模型、制图分享】数字技术力量下传统村落景观修复演进的特征与机制研究——以岳阳市张谷英村为例(GIS空间分析、点云提取)

文献介绍 景观修复作为弘扬中华优秀传统文化的重要方式&#xff0c;如何在乡村数字化新时代背景下&#xff0c;把握传统村落景观修复的数字赋能&#xff0c;已成为推动中华优秀传统文化创造性转化与创新性发展亟需解决的科学问题。运用深度访谈、GIS空间分析、点云数据提取等方…

html+css+js网页设计 婚庆类型12个页面

htmlcssjs网页设计 婚庆类型12个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…

FreeRTOS 低功耗模式

正如STM32的裸机编程一样&#xff0c;FreeRTOS通用提供了低功耗模式。 前面说的很明白&#xff0c;FreeRTOS的低功耗模式实际上还是基于STM32的低功耗模式指令进入睡眠模式来实现的&#xff0c;并且只要中断来临&#xff0c;就会退出低功耗&#xff0c;FreeRTOS的系统时钟是最底…

猫头虎分享:Python库 Statsmodels 的简介、安装、用法详解入门教程

猫头虎分享&#xff1a;Python库 Statsmodels 的简介、安装、用法详解入门教程 &#x1f42f; 引言 &#x1f3af; 今天猫头虎带您 深入探讨 Statsmodels 这个在数据分析和统计建模领域非常重要的Python库。最近有粉丝在评论区问道&#xff1a;“猫哥&#xff0c;如何使用 St…

USB端点

USB端点 各端点使用循环冗余校验&#xff08;CRC&#xff09;来检测传输中发生的错误。 根据 USB 规范&#xff0c;设备端点是 USB 设备中一个独特的可寻址部分&#xff0c;它作为主机和设备间通信流的信息源或库。 USB 枚举和配置一节介绍了设备向默认地址做出响应的步骤。 枚…

能进大厂的自动化测试面试题

前言 每次到金九银十都避免不了要聊一聊面试题了&#xff0c;如今九月已经是中下旬了&#xff0c;马上就要到十月份了&#xff0c;还在投简历找工作的小伙伴可以看看我这几天发的文章&#xff0c;最近发的都是面试题&#xff0c;如果需要笔者教一下大家怎么写简历的小伙伴可以…

光伏高压并网升压箱变

在当今能源领域的变革浪潮中&#xff0c;光伏能源以其清洁、可再生的显著优势&#xff0c;成为了备受瞩目的焦点。而光伏高压并网升压箱变&#xff0c;则是实现光伏电能顺利接入高压电网的核心设备。 光伏高压并网升压箱变宛如光伏能源系统中的一位“大力士”&#xff0c;承担着…

一张图浏览CSS Functions

点我CSS Functions思维导图下载 函数文章链接示例属性函数var attr env介绍访问文章示例地址

银河麒麟编译opencv库并配置qt环境

1.opencv下载版本:opencv4.5.5,qt安装的是qt5.12.11,系统版本: 2.首先应该安装cmake工具: 下载地址:https://cmake.org/download/ 安装步骤: 1)解压; 2)进入解压后的文件夹cd cmake-3.30.2 3)./bootstrap 4)sudo make 5)sudo make install 3.下载opencv,下…

实现 GridLayoutManger 和 StaggeredGridLayoutManager 混排的工具类

序言 最近项目中要实现瀑布流的混排&#xff0c;于是写了一些工具类来实现。使用了这个工具类&#xff0c;可以处理混排&#xff0c;可以处理间距。都集成在一个接口中。 最后效果类似这样。 工具类 GridItemUI 下面的这个类是用来实现在GridLayouManger中混排的。 packag…

硬件-PCB-正片(常用默认)和负片

文章目录 问题&#xff1a;什么是PCB的正片和负片&#xff1f;1.正片设计默认是无铜的&#xff08;常用&#xff09;2.负片设计是默认有铜的3.网友评论道友&#xff1a;我们的对手从来不是别人&#xff0c;而是自己。如果有什么必须战胜&#xff0c;那就是过去的自己。战胜自己…