STM32第十九课:FreeRTOS移植和使用

目录

  • 需求
  • 一、FreeRtos概要
  • 二、移植FreeRtos
    • 1.复制源码
    • 2.内存空间分配和内核相关接口
    • 3.FreeRTOSConfig.h
    • 4.在工程中添加.c.h
  • 三、任务块操作
    • 1.创建任务
    • 2.任务挂起,恢复,删除
  • 四、需求实现代码


需求

1.将FreeRtos(嵌入式实时操作系统)移植到STM32中。
2.在该系统中实现任务的创建、挂起、恢复和删除。
3.将之前写的传感器模块的数据获取,移植到FreeRtos(嵌入式实时操作系统)环境下。
在这里插入图片描述
在这里插入图片描述


一、FreeRtos概要

STM32裸机运行代码:
在这里插入图片描述
加入FreeRtos后:
在这里插入图片描述
由此可见,由于单片机只有一个核心,同一时间下只能处理一件事。如果用户想要实现多个任务并行的效果,可以通过加入FreeRtos(嵌入式实时操作系统),操作系统可以让STM32实现任务的快速切换,从而给人一种多个任务并行的错觉。
在这里插入图片描述

二、移植FreeRtos

  打开想要移植FreeRtos的工程,把主函数清空,只留一个while(1)。由于FreeRtos是任务块操作,所以之前写的程序就没用了。
移植后使用了三个中断服务函数:
1.SVC中断服务函数:上下切换中断,FreeRtos实现任务切换
2.PendSVC中断服务函数:任务挂起中断。
3.SysTick中断服务函数:FreeRtos运行的时间基准

#define vPortSVCHandler SVC_Handler	  //上下切换中断,FreeRtos实现任务切换
#define xPortPendSVHandler PendSV_Handler		//任务挂起中断
#define xPortSysTickHandler SysTick_Handler	//FreeRtos运行的时间基准

1.复制源码

先打开移植的文件夹:

在这里插入图片描述
将源码直接复制到想要移植的工程文件下,改名为FreeRtos:
在这里插入图片描述

2.内存空间分配和内核相关接口

在这里插入图片描述
在portable文件夹中找到MemMang文件夹,该文件夹放着的就是内存分配文件,我们选择4就行。
在这里插入图片描述
port,就是内核相关的接口文件,是必要添加的。

3.FreeRTOSConfig.h

在这里插入图片描述
打开样例文件夹,找到相对应的芯片,将FReeRTOSconfig.h文件复制过来即可。

4.在工程中添加.c.h

.c
在这里插入图片描述
.h
在这里插入图片描述

其中,FreeRTOSConfig.h 是直接从 demo 文件夹下面拷贝过来的,该头文件对裁剪整个FreeRTOS 所需的功能的宏均做了定义,有些宏定义被使能,有些宏定义被失能,一开始我们只需要配置最简单的功能即可。要想随心所欲的配置 FreeRTOS 的功能,必须对这些宏定义的功能有所掌握。

#define configUSE_TIME_SLICING 1 //使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 //硬件计算前导零指令,如果所使用的, MCU 没有这些硬件指令的话此宏应该设置为 0
#define configUSE_TICKLESS_IDLE 0 //置 1:使能低功耗 tickless 模式;置 0:保持系统节拍(tick)中断一直运行
#define configUSE_QUEUE_SETS 1 //启用队列
#define configUSE_TASK_NOTIFICATIONS 1 //开启任务通知功能,默认开启
#define configUSE_MUTEXES 1 //使用互斥信号量
#define configUSE_RECURSIVE_MUTEXES 1 //使用递归互斥信号量
#define configUSE_COUNTING_SEMAPHORES 1 //为 1 时使用计数信号量
#define configQUEUE_REGISTRY_SIZE 10 //设置可以注册的信号量和消息队列个数
#define configUSE_APPLICATION_TASK_TAG 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1 //支持动态内存申请
#define configUSE_MALLOC_FAILED_HOOK 0 //使用内存申请失败钩子函数
#define configCHECK_FOR_STACK_OVERFLOW 1// 大于 0 时启用堆栈溢出检测功能,如果使用此功能用户必须提供一个栈溢出钩子函数如果使用的话此值可以为 1 或者 2,因为有两种栈溢出检测方法
#define configGENERATE_RUN_TIME_STATS 0 //启用运行时间统计功能
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configUSE_TIMERS 1 //启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 10 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小
//可选函数配置选项
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
//中断服务函数 也可以修改起始文件
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

三、任务块操作

调度
和裸机操作不同,操作系统中执行的是一个一个任务块,通过任务调度器(使用相关的调度算法)来决定当前时刻要执行哪个任务。
调度方式主要有两种:
1.抢占式调度:任务优先级不同时使用。每个任务都有自己的优先级,高优先级的任务会抢占低优先级的任务。
2.时间片调度:任务优先级相同时使用。当多个任务优先级相同时,任务调度器会在每一次系统节拍到的时候切换任务。
其实说白了就是:STM32执行的是线性代码,只有中断能打断。而FreeRtos执行的是不同等级的任务块,等级越高任务块就越先执行相同等级的任务块执行时系统会来回切换
优先级不能设置为0,因为FreeRtos的空闲任务优先级为0,一般情况下我们不去抢。

任务状态

状态含义
运行态CPU正在执行的任务。注意:在STM32中,同一时间仅一个任务处于运行态
就绪态该任务能够被执行,但目前还未被执行,那么该任务就处于就绪态。
阻塞态如果一个任务因延时或等待外部事件发生,那么这个任务就处于阻塞态。
挂起态类似暂停,调用函数 vTaskSuspend() 进入挂起态,需要调用恢复函数vTaskResume()才可以进入就绪态 。

1.创建任务

添加FreeRTOS相关头文件

//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"

创建一个句柄,TaskHandle_t 类型

TaskHandle_t LED_TaskHandle;//LED

写与句柄对应的任务函数,通常要加while(1)每个任务都是1个无限循环程序,内容根据需求来定。

void Led_Task(void *p)
{uint8_t i=0;while(1){i++;printf("i=%d\r\n",i);Led_Toggle(1);Delay_nms(300);}
}

定义一个BaseType_t变量

BaseType_t Ret = pdPASS;

使用xTaskCreate()创建任务块,返回值由BaseType_t类型变量承接,返回值为pdPASS(1)时即创建成功

	Ret = xTaskCreate(  Led_Task,"LED1_toggle",50,//栈深度,32位单片机*4NULL,2,&LED_TaskHandle);if(Ret==pdPASS){printf("LED_Task创建成功!\r\n");}

参数1:实现任务的函数名
参数2:自己起一个任务名
参数3:分配空间,栈深度(32位单片机*4)
参数4:任务函数传参时使用
参数5:任务优先级(越高优先级越高)
参数6:该任务的句柄

最后,使用vTaskStartScheduler()函数开始调度就完成了。

vTaskStartScheduler();

2.任务挂起,恢复,删除

挂起
使用vTaskSuspend()函数即可,参数只有一个:想要挂起任务的句柄。
恢复
使用vTaskResume()函数即可,参数只有一个:想要恢复任务的句柄。
删除
使用vTaskDelete()函数即可,参数只有一个:想要删除任务的句柄。

printf("挂起LED\r\n");vTaskSuspend(LED_TaskHandle);//挂起
printf("继续LED\r\n");vTaskResume(LED_TaskHandle);//继续
printf("删除LED\r\n");vTaskDelete(LED_TaskHandle);//删除

四、需求实现代码

在该系统中实现任务的创建、挂起、恢复和删除

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "usart.h"
#include "key.h"
TaskHandle_t LED_TaskHandle;//LED
TaskHandle_t KEY_TaskHandle;//KEYvoid Led_Task(void *p)
{uint8_t i=0;while(1){i++;printf("i=%d\r\n",i);Led_Toggle(1);Delay_nms(300);}
}void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:{printf("挂起LED\r\n");vTaskSuspend(LED_TaskHandle);}break;//挂起case 2:{printf("继续LED\r\n");vTaskResume(LED_TaskHandle);}break;//继续case 3:{printf("删除LED\r\n");vTaskDelete(LED_TaskHandle);}break;case 4:{	BaseType_t Ret = pdPASS;	Ret = xTaskCreate(  Led_Task, "LED1_toggle",50,NULL,2,&LED_TaskHandle);if(Ret==pdPASS){printf("LED_Task创建成功!\r\n");}};break;}vTaskDelay(10);}
}int main()
{Led_Init();key_Init();Usart1_Config();BaseType_t Ret = pdPASS;Ret = xTaskCreate(  Led_Task,"LED1_toggle",50,//栈深度,32位单片机*4NULL,2,&LED_TaskHandle);if(Ret==pdPASS){printf("LED_Task创建成功!\r\n");}Ret = xTaskCreate(  KEY_Task,"KEY_Task",80,//栈深度,32位单片机*4NULL,2,&KEY_TaskHandle);if(Ret==pdPASS){printf("KEY_Task创建成功\r\n");}printf("开始调度!\r\n");vTaskStartScheduler();while(1){}
}

将之前写的传感器模块的数据获取,移植到FreeRtos(嵌入式实时操作系统)环境下
main.c

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"
#include "su03t.h"
#include "dht11.h"
#include "kqm.h"//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "usart.h"
#include "key.h"
TaskHandle_t Deal_TaskHandle;//数据处理void Data_Task(void *p)
{while(1){Get_Smoke_Light_MidValue();DHT11_ReadData();Delay_nms(300);KQM_DealData();Su03tDealData();}
}int main()
{RGBpwm_Config();Kqm_U4Config();Su03t_U5Config();DHT11_Config();	 Adc_Config();Led_Init();key_Init();Usart1_Config();BaseType_t Ret = pdPASS;Ret = xTaskCreate(  Data_Task,"DealData",100,//栈深度,32位单片机*4NULL,2,&Deal_TaskHandle);if(Ret==pdPASS){printf("语音创建成功!\r\n");}printf("开始调度!\r\n");vTaskStartScheduler();while(1){}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ts使用typeorm实现db创建

1.新建基础架构 ①创建项目文件名, mkdir ‘名称’ ->cd ‘文件名’ -> mkdir ‘src’->npm init mkdir fileName cd fileName mkdir src npm init在当前项目名目录下执行npm init,按照默认执行就会创建package.json. 之后执行 npm i jest/globals casl/ability bcr…

755M全球山脉数据集分享

我们在《548M高精度全球国界数据》和《270M全球流域矢量数据》文中,为你分享过全球的国界数据和水系流域数据。 现在再为你分享755M全球山脉数据集,请在文末查看该数据的领取方法。 755M全球山脉数据集 全球山脉数据集,提供了在全球山地生…

【企业级监控】Zabbix监控网站并发连接数

Zabbix自定义监控项与触发器 文章目录 Zabbix自定义监控项与触发器资源列表基础环境前言一、什么是zabbix的Key值二、获取远程Key值2.1、获得主机的Key值2.2、被监控端安装Agent2.3、zabbix_get命令获取Agent数据举例2.3.1、zabbx_get获取cpu核心数2.3.2、获取目标主机系统和内…

ESP32CAM物联网教学11

ESP32CAM物联网教学11 霍霍webserver 在第八课的时候,小智把乐鑫公司提供的官方示例程序CameraWebServer改成了明码,这样说明这个官方程序也是可以更改的嘛。这个官方程序有四个文件,一共3500行代码,看着都头晕,小智决…

opencascade AIS_InteractiveContext源码学习8 trihedron display attributes

AIS_InteractiveContext 前言 交互上下文(Interactive Context)允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是,对于已经被交互上下文识别的交互对象,必须使用上下文方法进行…

探索IP形象设计:快速掌握设计要点

随着市场竞争的加剧,越来越多的企业开始关注品牌形象的塑造和推广。在品牌形象中,知识产权形象设计是非常重要的方面。在智能和互联网的趋势下,未来的知识产权形象设计可能会更加关注数字和社交网络。通过数字技术和社交媒体平台,…

年轻人「躺平」、「摆烂」现象的根源是什么?

年轻人「躺平」、「摆烂」现象的根源是什么? 穷人没有资格躺平 我可以躺平吗?当然可以了! 对于有些人来说是躺平在房车里,直接开到命运的终点;而你是躺在马路中间,被命运的车轮反复碾压。 中国一线城市的00后,他们的父母多是没有哥哥、姐姐、弟弟、妹妹的独生子女,…

S7-200smart与C#通信

https://www.cnblogs.com/heizao/p/15797382.html C#与PLC通信开发之西门子s7-200 smart_c# s7-200smart通讯库-CSDN博客https://blog.csdn.net/weixin_44455060/article/details/109713121 C#上位机读写西门子S7-200SMART PLC变量 教程_哔哩哔哩_bilibilihttps://www.bilibili…

昇思25天学习打卡营第19天|sea_fish

打卡第19天。本次学习的内容为生成式中的Diffusion扩散模型。记录学习的过程。 模型简介 什么是Diffusion Model? 如果将Diffusion与其他生成模型(如Normalizing Flows、GAN或VAE)进行比较,它并没有那么复杂,它们都…

【C语言报错已解决】格式化字符串漏洞(Format String Vulnerability)

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 引言:一、问题描述:1.1 报错示例:1.2 报错分析:1.3 解决思路&#xff…

Qt中文个数奇数时出现问号解决

Qt中文个数奇数时出现问号解决 目录 Qt中文个数奇数时出现问号解决问题背景问题场景解决方案 问题背景 最近在开发一个小工具,涉及到一些中文注释自动打印,于是摸索如何把代码里面的中文输出到csv文件中,出现了乱码,按照网上的攻…

RedisTemplate 中序列化方式辨析

在Spring Data Redis中,RedisTemplate 是操作Redis的核心类,它提供了丰富的API来与Redis进行交互。由于Redis是一个键值存储系统,它存储的是字节序列,因此在使用RedisTemplate时,需要指定键(Key&#xff09…

Hi3861 OpenHarmony嵌入式应用入门--HTTPD

httpd 是 Apache HTTP Server 的守护进程名称,Apache HTTP Server 是一种广泛使用的开源网页服务器软件。 本项目是从LwIP中抽取的HTTP服务器代码; Hi3861 SDK中已经包含了一份预编译的lwip,但没有开启HTTP服务器功能(静态库无法…

Apache Doris:下一代实时数据仓库

Apache Doris:下一代实时数据仓库 概念架构设计快速的原因——其性能的架构设计、特性和机制基于成本的优化器面向列的数据库的快速点查询数据摄取数据更新服务可用性和数据可靠性跨集群复制多租户管理便于使用半结构化数据分析据仓一体分层存储 词条诞生技术概述适…

谷粒商城学习笔记-23-分布式组件-SpringCloud Alibaba-Nacos配置中心-简单示例

之前已经学习了使用Nacos作为注册中心,这一节学习Nacos另外一个核心功能:配置中心。 一,Nacos配置中心简介 Nacos是一个易于使用的平台,用于动态服务发现和配置管理。作为配置中心,Nacos提供了以下核心功能和优势&am…

集成运算放大器的内部电路结构

原文出自微信公众号【小小的电子之路】 在集成电路问世之前,放大电路都是由晶体管、二极管、电阻、电容等分立元件组成,称为晶体管放大电路,但是复杂的计算限制了这类电路的推广。随着集成电路行业的发展,晶体管放大电路被制作在半…

Vue3 前置知识

1. Vue3 简介 2020年9月18日,Vue.js发布版3.8版本,代号:one Piece(海贼王)经历了:4800次提交、40个RFC、600次PR、300贡献者官方发版地址:Release v3.0.0 One Piecevuejs/,core截止2023年10月,最新的公开版…

Python爬虫速成之路(3):下载图片

hello hello~ ,这里是绝命Coding——老白~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页:绝命Coding-CSDN博客 &a…

开源AI生成连续一致性儿童故事书; GraphRAG结合本地版Ollama;AI辅助老年人用餐;开源无代码AI工作流VectorVein

✨ 1: SEED-Story SEED-Story 是一种能生成包含一致性图像的多模态长篇故事的机器学习模型,配套数据集已开放。 SEED-Story 是一种多模态长故事生成模型,具备生成包含丰富且连贯的叙事文本和一致性高的人物和风格图像的能力。此模型基于 SEED-X 构建。…

论文阅读【时空+大模型】ST-LLM(MDM2024)

论文阅读【时空大模型】ST-LLM(MDM2024) 论文链接:Spatial-Temporal Large Language Model for Traffic Prediction 代码仓库:https://github.com/ChenxiLiu-HNU/ST-LLM 发表于MDM2024(Mobile Data Management&#xf…