FreeRTOS入门教程(队列的概念及相关函数介绍)

news2024/11/19 19:18:20

文章目录

  • 前言
  • 一、队列概念
  • 二、队列的使用方法
    • 1.创建队列
      • 动态创建
      • 静态创建
    • 2.复位队列
    • 3.删除队列
    • 4.写队列
    • 5.读队列
    • 6.查询队列
    • 7.覆盖/查看
      • 覆盖
      • 查看
  • 总结


前言

本篇文章将带大家学习FreeRTOS中的队列,掌握什么是队列,并且学习如何使用队列,在什么场景会使用到队列。

一、队列概念

FreeRTOS中的队列(Queue)是一种用于在任务之间传递数据的数据结构,它遵循先进先出(FIFO)的原则。队列在实时嵌入式系统中非常有用,因为它们允许任务之间以安全和同步的方式共享信息,而无需使用全局变量或其他不安全的方法。以下是有关FreeRTOS中队列的详细解释:

1.队列的用途:

队列主要用于任务之间的数据传递和通信。它们提供了一种机制,使一个任务能够将数据发送到队列,而另一个任务可以从队列中接收数据。这种方式允许任务在不同的执行速度下工作,以及以异步的方式进行通信。

2.队列的特性:

FIFO原则:队列遵循先进先出的原则,即最早进入队列的数据项将首先被取出。
有限容量:队列通常有一定的容量限制,这意味着一旦队列满了,试图向其添加更多数据项的操作将被阻塞,直到有空间可用。
阻塞操作:队列的操作可以是阻塞的,这意味着任务可以在队列为空或队列已满时被阻塞,直到条件满足为止。

队列操作图解:
在这里插入图片描述
下面举一个两个任务之间使用队列进行通信的例子:

Task1不断向队列中写入数据,Task2不断从队列中读取数据,当读取完第一个数据时,队列中第二个数据将向前移动一个位置变成第一个数据。

在这里插入图片描述

二、队列的使用方法

使用队列的流程:创建队列、写队列、读队列、删除队列。

1.创建队列

动态创建

动态创建队列是在运行时使用函数来分配内存以创建队列。这需要使用动态内存分配函数,如pvPortMalloc()来分配内存,并使用vQueueDelete()函数来删除队列以释放内存。

动态创建队列:xQueueCreate()

QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);

uxQueueLength:这是队列的长度,即队列可以容纳的数据项数量。通常以数字的形式表示。

uxItemSize:这是队列中每个数据项的大小,以字节为单位。通常用sizeof()操作符来确定。

函数返回值:

如果队列创建成功,将返回一个有效的队列句柄(QueueHandle_t类型)。
如果队列创建失败,返回值将为NULL。

使用示例:

QueueHandle_t xQueue;
xQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);
if (xQueue == NULL) {
    // 队列创建失败处理
}

// 使用队列

vQueueDelete(xQueue);

静态创建

静态创建队列是在编译时通过定义全局变量或静态变量来创建队列。这种方法在编译时为队列分配内存,不需要在运行时动态分配和释放内存。这种方法适用于内存资源有限且可预先确定的情况。

静态创建队列:xQueueCreateStatic()

QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t *pucQueueStorageBuffer, StaticQueue_t *pxStaticQueue);

uxQueueLength:这是队列的长度,即队列可以容纳的数据项数量。通常以数字的形式表示。

uxItemSize:这是队列中每个数据项的大小,以字节为单位。通常用sizeof()操作符来确定。

pucQueueStorageBuffer:这是指向用于存储队列数据的静态缓冲区的指针。这个缓冲区的大小应该足够容纳指定长度和数据项大小的队列。

pxStaticQueue:这是指向StaticQueue_t类型的静态队列结构的指针。StaticQueue_t是FreeRTOS内部用于管理静态队列的数据结构。

函数返回值:

如果队列创建成功,将返回一个有效的队列句柄(QueueHandle_t类型)。
如果队列创建失败,返回值将为NULL。

使用示例:

xStaticQueue_t xQueueBuffer;
StaticQueue_t xStaticQueue;

QueueHandle_t xQueue;
xQueue = xQueueCreateStatic(QUEUE_LENGTH, ITEM_SIZE, xQueueBuffer.ucQueueStorage, &xStaticQueue);
if (xQueue == NULL) {
    // 队列创建失败处理
}

// 使用队列

2.复位队列

复位队列:xQueueReset()

BaseType_t xQueueReset(QueueHandle_t xQueue);

xQueue:这是要复位的队列的句柄,即要操作的队列。

函数返回值:

如果成功复位队列,函数返回pdPASS。
如果队列复位失败,函数返回pdFAIL。

使用示例:

// 创建一个队列
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));

// 复位队列
if (xQueueReset(xQueue) == pdPASS) {
    // 队列复位成功
} else {
    // 队列复位失败
}

3.删除队列

删除队列:vQueueDelete()

void vQueueDelete(QueueHandle_t xQueue);

xQueue:要删除的队列的句柄,即要操作的队列。

使用示例:

// 创建一个队列
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));

// 删除队列
vQueueDelete(xQueue);

4.写队列

写队列:xQueueSend() 和 xQueueSendFromISR()

xQueueSend() 用于从任务中发送数据到队列。

BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);

xQueue:要写入的队列的句柄。

pvItemToQueue:指向要发送的数据的指针。

xTicksToWait:如果队列已满,任务将等待的最大时间(以时钟节拍为单位),或者传递portMAX_DELAY以一直等待。

xQueueSendFromISR() 用于从中断服务程序中发送数据到队列。

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);

xQueue:要写入的队列的句柄。

pvItemToQueue:指向要发送的数据的指针。

pxHigherPriorityTaskWoken:如果发送导致了高优先级任务唤醒,则设置为pdTRUE,否则为pdFALSE。

函数返回值:

xQueueSend() 成功写入队列返回pdPASS,否则返回pdFAIL。
xQueueSendFromISR() 成功写入队列返回pdPASS,否则返回pdFAIL。

使用示例:

// 创建一个队列
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int data = 42;

// 写队列(任务中)
if (xQueueSend(xQueue, &data, portMAX_DELAY) == pdPASS) {
    // 数据成功写入队列
}

// 写队列(中断服务程序中)
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xQueueSendFromISR(xQueue, &data, &xHigherPriorityTaskWoken) == pdPASS) {
    // 数据成功写入队列并可能唤醒了高优先级任务
}

5.读队列

读队列:xQueueReceive() 和 xQueueReceiveFromISR()

xQueueReceive() 用于从任务中读取队列中的数据。

BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

xQueue:要读取的队列的句柄。

pvBuffer:指向存储接收数据的缓冲区的指针。

xTicksToWait:如果队列为空,任务将等待的最大时间(以时钟节拍为单位),或者传递portMAX_DELAY以一直等待。

xQueueReceiveFromISR() 用于从中断服务程序中读取队列中的数据。

BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);

xQueue:要读取的队列的句柄。

pvBuffer:指向存储接收数据的缓冲区的指针。

pxHigherPriorityTaskWoken:如果接收导致了高优先级任务唤醒,则设置为pdTRUE,否则为pdFALSE。

函数返回值:

xQueueReceive() 成功接收数据返回pdPASS,否则返回pdFAIL。
xQueueReceiveFromISR() 成功接收数据返回pdPASS,否则返回pdFAIL。

使用示例:

// 创建一个队列
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int receivedData;

// 从队列中读取数据(任务中)
if (xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdPASS) {
    // 数据成功从队列中读取
}

// 从队列中读取数据(中断服务程序中)
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xQueueReceiveFromISR(xQueue, &receivedData, &xHigherPriorityTaskWoken) == pdPASS) {
    // 数据成功从队列中读取并可能唤醒了高优先级任务
}

6.查询队列

查询队列:uxQueueMessagesWaiting() 和 uxQueueSpacesAvailable()

这些函数用于查询队列中当前等待的消息数量和剩余可用空间。

UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue);

xQueue:要查询的队列的句柄。

UBaseType_t uxQueueSpacesAvailable(QueueHandle_t xQueue);

xQueue:要查询的队列的句柄。

使用示例:

// 创建一个队列
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));

// 查询队列中等待的消息数量
UBaseType_t messagesWaiting = uxQueueMessagesWaiting(xQueue);

// 查询队列中剩余的可用空间
UBaseType_t spacesAvailable = uxQueueSpacesAvailable(xQueue);

7.覆盖/查看

覆盖

xQueueOverwrite()

BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void *pvItemToQueue);

xQueue:要覆写的队列句柄。
pvItemToQueue:指向要写入队列的数据的指针。
函数返回值:

如果成功写入队列,函数返回 pdPASS。
如果队列已满,数据将被覆写,函数同样返回 pdPASS。
如果队列操作失败,函数返回 errQUEUE_FULL。

使用示例:

QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int data = 42;

if (xQueueOverwrite(xQueue, &data) == pdPASS) {
    // 数据成功写入队列(即使队列已满)
}

xQueueOverwriteFromISR()

BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);

xQueue:要从中断服务程序中覆写的队列句柄。
pvItemToQueue:指向要写入队列的数据的指针。
pxHigherPriorityTaskWoken:如果操作导致较高优先级任务唤醒,则设置为 pdTRUE,否则为 pdFALSE。
函数返回值:

如果成功写入队列,函数返回 pdPASS。
如果队列已满,数据将被覆写,函数同样返回 pdPASS。
如果队列操作失败,函数返回 errQUEUE_FULL。

使用示例:

QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int data = 42;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

if (xQueueOverwriteFromISR(xQueue, &data, &xHigherPriorityTaskWoken) == pdPASS) {
    // 数据成功从中断服务程序中写入队列(即使队列已满)
}

查看

xQueuePeek()

BaseType_t xQueuePeek(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

xQueue:要查看的队列句柄。
pvBuffer:存储查看结果的指针。
xTicksToWait:如果队列为空,任务将等待的最大时间(以时钟节拍为单位),或者传递 portMAX_DELAY 以一直等待。
函数返回值:

如果成功查看队列中的数据,函数返回 pdTRUE。
如果队列为空或等待超时,函数返回 pdFALSE。

使用示例:

QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int peekedData;

if (xQueuePeek(xQueue, &peekedData, 0) == pdTRUE) {
    // 数据成功从队列中查看
}

xQueuePeekFromISR()

BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *pvBuffer);

xQueue:要从中断服务程序中查看的队列句柄。
pvBuffer:存储查看结果的指针。
函数返回值:

如果成功查看队列中的数据,函数返回 pdTRUE。
如果队列为空,函数返回 pdFALSE。

使用示例:

QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int peekedData;

if (xQueuePeekFromISR(xQueue, &peekedData) == pdTRUE) {
    // 数据成功从中断服务程序中查看队列
}

总结

本篇文章主要详细的讲解了队列的概念和队列的使用方法,看完文章后大家可以使用代码进行测试巩固复习。

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

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

相关文章

集成学习

集成学习(Ensemble Learning) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/27689464集成学习就是组合这里的多个弱监督模型以期得到一个更好更全面的强监督模型,集成学习潜在的思想是即便某一个弱分类器得到了错误的预测,其他的弱分类器…

Pytorch基础:Tensor的permute方法

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html 在Pytorch中,permute是Tensor的一个重要方法,同时它也是一个torch模块中的一个函数,它们的语法如下所示。 Tensor.permute(*dims) → Tensor torch.perm…

PbootCMS SQL注入漏洞

漏洞复现 访问漏洞url 数据库是mysql 构造payload,条件为假时,未查到任何数据 http://x.x.x/index.php?search 1select 0页面回显 构造payload,条件为真时,查询到数据 1select1文笔生疏,措辞浅薄,望各…

邮箱注册实现(二)注册接口实现

如果邮箱地址错误或非法,运行时会报错。因此需要增加校验: Validated RestController RequestMapping("/api/auth") public class AuthorizeController {ResourceAccountService service;GetMapping("/ask-code")public RestBean&l…

typescript 类型声明文件

typescript 类型声明文件概述 在今天几乎所有的JavaScript应用都会引入许多第三方库来完成任务需求。这些第三方库不管是否是用TS编写的,最终都要编译成JS代码,才能发布给开发者使用。6我们知道是TS提供了类型,才有了代码提示和类型保护等机…

R实现数据分布特征的视觉化——多笔数据之间的比较

大家好,我是带我去滑雪! 如果要对两笔数据或者多笔数据的分布情况进行比较,Q-Q图、柱状图、星形图都是非常好的选择,下面开始实战。 (1)绘制Q-Q图 首先导入数据bankwage.csv文件,该数据集…

[MIT6.824] Lab 3: Fault-tolerant Key/Value Service

[MIT6.824] Lab 3: Fault-tolerant Key/Value Service 目标 通过在Lab2中实现的Raft库,构建一个可容灾的KV数据库。 需要实现的服务有三种操作: Put(key, value) key和value都是string,put设置指定key的value. Append(key, arg) 将arg append到key对…

『Linux』Linux环境搭建 | 阿里云云服务器白嫖 | Xshell环境配置

🔥博客主页: 小羊失眠啦 🔖系列专栏: C语言、Linux 🌥️每日语录:时间,都是公平的,不公平的,只是现在的自己,对未来的自己。 ❤️感谢大家点赞👍收…

大华城市安防系统平台任意文件下载漏洞

一、漏洞描述 大华城市安防监控系统平台是一款集视频、报警、存储、管理于一体的综合安防解决方案。该平台支持多种接入方式,包括网络视频、模拟视频、数字视频、IP电话、对讲机等。此外,该平台还支持多种报警方式,包括移动侦测、区域入侵、…

Geteway

大家好我是苏麟今天带来Geteway. Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单…

【C++】STL详解(十一)—— unordered_set、unordered_map的介绍及使用

​ ​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:C学习 🎯长路漫漫浩浩,万事皆有期待 上一篇博客:【C】STL…

ROS机械臂开发-开发环境搭建【一】

目录 前言环境配置docker搭建Ubuntu环境安装ROS 基础ROS文件系统 bugs 前言 想系统学习ROS,做一些机器人开发。因为有些基础了,这里随便写写记录一下。 环境配置 docker搭建Ubuntu环境 Dockerfile # 基础镜像 FROM ubuntu:18.04 # 设置变量 ENV ETC…

数据结构课程设计题目——链表综合算法设计、带头双向循环链表、插入、显示、删除、修改、排序

文章目录 链表综合算法设计——校园人事信息系统1.要求2.代码实现(以带头双向循环链表为例)2.1基本程序结构2.2节点和链表的初始化2.3链表的插入2.4链表的显示2.5链表的删除2.6链表的修改2.7链表的排序(仿函数实现) 3.全部源码 链…

Arxdbg读取cad扩展属性

xdlist可以读取CAD实体属性,子实体的扩展属性看不到。 下载arxdbg,appload加载。 鼠标右键即可看见,选Entity Info。 查看xdata,dxfdata都可以看到扩展信息。

Python 无废话-办公自动化Excel修改数据

如何修改Excel 符合条件的数据?用Python 几行代码搞定。 需求:将销售明细表的产品名称为PG手机、HW手机、HW电脑的零售价格分别修改为4500、5500、7500,并保存Excel文件。如下图 Python 修改Excel 数据,常见步骤: 1&…

jmeter和性能测试

一。性能测试的概念 1.性能:就是软件质量属性中的 “ 效率 ” 特性 2.效率特性: 时间特性:指系统处理用户请求的响应时间 资源特性:指系统在运行过程中,系统资源的消耗情况 CPU 内存 磁盘IO(磁盘的写…

鸡群优化(CSO)算法(含MATLAB代码)

先做一个声明:文章是由我的个人公众号中的推送直接复制粘贴而来,因此对智能优化算法感兴趣的朋友,可关注我的个人公众号:启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法,经典的,或者是近几年…

TCP VS UCP

程序员写网络程序,主要编写的应用层代码! 真正要发这个数据,需要上层协议调用下层协议,应用层要调用传输层,则传输层给应用层提供一组api,统称为:soket api 基于UDP的api 基于TCP的api 这两个协…

Godot 初学

前言 因为9月份 Unity一顿安装计费的骚操作,导致世界开发者对于Unity 随意修改开发条例,追溯之前开发游戏版本感到愤怒。Unity是全球游戏使用率超过50%的引擎,Unity和Unreal是最主流的第三方游戏引擎。除非你是大厂可以自研引擎,…

阿里云服务器活动价格及配置整理表(多配置报价)

2023年阿里云服务器租用费用,阿里云轻量应用服务器2核2G3M带宽轻量服务器一年108元,2核4G4M带宽轻量服务器一年297.98元12个月,CS云服务器e系列2核2G配置182元一年、2核4G配置365元一年、2核8G配置522元一年,阿里云u1服务器2核4G、…