【FreeRTOS】消息队列——简介、常用API函数、注意事项、项目实现

news2025/2/23 3:42:09

在嵌入式系统开发中,任务间的通信是非常常见的需求。FreeRTOS提供了多种任务间通信的机制,其中之一就是消息队列。消息队列是一种非常灵活和高效的方式,用于在不同的任务之间传递数据。通过消息队列,任务可以异步地发送和接收消息,从而实现任务间的数据交换和协作。

在本篇博文中,我们将深入探讨FreeRTOS中消息队列的使用,包括如何创建和初始化消息队列,以及如何在任务中发送和接收消息。我们还将讨论消息队列的特性和限制,并提供一些实际的示例代码,以帮助读者更好地理解消息队列的工作原理和用法。通过本篇博文,读者将能够掌握在FreeRTOS中有效地利用消息队列进行任务间通信的技巧和方法。


文章目录

    • 1.消息队列简介
      • 1.1 特性
      • 1.2 消息队列数据存储
      • 1.3 出队阻塞
      • 1.4 入队阻塞
      • 1.5 消息队列操作示图
      • 1.6 消息队列控制块
    • 2.常用消息队列API函数
      • 2.1 消息队列创建函数 `xQueueCreate()`
      • 2.2 消息队列静态创建函数 `xQueueCreateStatic()`
      • 2.3 消息队列删除函数 `vQueueDelete()`
      • 2.4 向消息队列发送消息函数
        • 2.4.1 `xQueueSend()`与`xQueueSendToBack()`
        • 2.4.2 `xQueueSendFromISR()`与 `xQueueSendToBackFromISR()`
        • 2.4.3 `xQueueSendToFront()`
        • 2.4.4 `xQueueSendToFrontFromISR()`
        • 2.4.5 `xQueueGenericSend()`
        • 2.4.6 `xQueueGenericSendFromISR()`
      • 2.5 从消息队列读取消息函数
        • 2.5.1 `xQueueReceive()`与`xQueuePeek()`
        • 2.5.2 `xQueueReceiveFromISR()`与 `xQueuePeekFromISR()`
    • 3.消息队列使用注意事项
    • 4.示例项目
      • stm32示例代码:
      • 项目解释:


1.消息队列简介

队列又称消息队列,是一种常用于任务间通信数据结构,队列可以在任务与任务间中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息。


1.1 特性

FreeRTOS 中使用队列数据结构实现任务异步通信工作,具有如下特性

  • 消息支持先进先出方式排队,支持异步读写工作方式。
  • 读写队列均支持超时机制。
  • 消息支持后进先出方式排队,往队首发送消息(LIFO)。
  • 可以允许不同长度(不超过队列节点最大值)的任意类型消息。
  • 一个任务能够从任意一个消息队列接收和发送消息。
  • 多个任务能够从同一个消息队列接收和发送消息。
  • 当队列使用结束后,可以通过删除队列函数进行删除。

1.2 消息队列数据存储

通常队列采用先进先出(FIFO)的存储缓冲机制,也可以使用 LIFO 的存储缓冲,也就是后进先出

数据发送到队列中会导致数据拷贝,也就是将要发送的数据拷贝到队列中,这就意味着在队列中存储的是数据的原始值,而不是原数据的引用(即只传递数据的指针),这个也叫做值传递。


1.3 出队阻塞

当任务尝试从一个队列中读取消息的时候可以指定一个阻塞时间,这个阻塞时间就是当任务从队列中读取消息无效的时候任务阻塞的时间。


1.4 入队阻塞

入队说的是向队列中发送消息,将消息加入到队列中。和出队阻塞一样,当一个任务向队列发送消息的话也可以设置阻塞时间。


1.5 消息队列操作示图

(1)创建队列

在这里插入图片描述

(2)向队列发送第一个消息

在这里插入图片描述

(3)向队列发送第二个消息
在这里插入图片描述

(4)从队列中读取消息

在这里插入图片描述


1.6 消息队列控制块

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2.常用消息队列API函数

2.1 消息队列创建函数 xQueueCreate()

在这里插入图片描述


2.2 消息队列静态创建函数 xQueueCreateStatic()

在这里插入图片描述


2.3 消息队列删除函数 vQueueDelete()

  • 原型void vQueueDelete(QueueHandle_t xQueue)
  • 功能:删除一个队列,释放相关资源
  • 参数:xQueue为要删除的队列句柄
  • 返回值:无

2.4 向消息队列发送消息函数

2.4.1 xQueueSend()xQueueSendToBack()

在这里插入图片描述
在这里插入图片描述


2.4.2 xQueueSendFromISR()xQueueSendToBackFromISR()

在这里插入图片描述
在这里插入图片描述


2.4.3 xQueueSendToFront()

在这里插入图片描述
在这里插入图片描述


2.4.4 xQueueSendToFrontFromISR()

在这里插入图片描述
在这里插入图片描述


2.4.5 xQueueGenericSend()
  • 原型
BaseType_t xQueueGenericSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition)
  • 功能:向队列发送数据

  • 参数

    • xQueue:要发送数据的队列句柄
    • pvItemToQueue:指向要发送的数据的指针
    • xTicksToWait:发送数据时的超时时间
    • xCopyPosition:指定数据拷贝的位置
  • 返回值
    如果数据成功发送到队列,则返回pdPASS;如果队列已满且超时,则返回errQUEUE_FULL;其他错误情况返回errQUEUE_FULL


2.4.6 xQueueGenericSendFromISR()
  • 原型
BaseType_t xQueueGenericSendFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t * pxHigherPriorityTaskWoken, BaseType_t xCopyPosition)
  • 功能:从ISR中向队列发送数据

  • 参数

    • xQueue:要发送数据的队列句柄
    • pvItemToQueue:指向要发送的数据的指针
    • pxHigherPriorityTaskWoken:指向一个变量的指针,用于指示是否有更高优先级的任务需要立即执行
    • xCopyPosition:指定数据拷贝的位置
  • 返回值:如果数据成功发送到队列,则返回pdPASS;如果队列已满,则返回errQUEUE_FULL;其他错误情况返回errQUEUE_FULL


2.5 从消息队列读取消息函数

2.5.1 xQueueReceive()xQueuePeek()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2.5.2 xQueueReceiveFromISR()xQueuePeekFromISR()

在这里插入图片描述

在这里插入图片描述


3.消息队列使用注意事项

  1. 使用 xQueueSend()xQueueSendFromISR()xQueueReceive()等这些函数之前应先创建需消息队列,并根据队列句柄进行操作。
  2. 队列读取采用的是先进先出 (FIFO) 模式,会先读取先存储在队列中的数据。当然也 FreeRTOS 也支持后进先出(LIFO) 模式,那么读取的时候就会读取到后进队列的数据。
  3. 在获取队列中的消息时候,我们必须要定义一个存储读取数据的地方,并且该数据区域大小不小于消息大小,否则,很可能引发地址非法的错误。
  4. 无论是发送或者是接收消息都是以拷贝的方式进行,如果消息过于庞大,可以将消息的地址作为消息进行发送、接收。
  5. 队列是具有自己独立权限的内核对象,并不属于任何任务。所有任务都可以向同一队列写入和读出。一个队列由多任务或中断写入是经常的事,但由多个任务读出倒是用的比较少。

4.示例项目

stm32示例代码:

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stm32f4xx.h"

#define QUEUE_LENGTH 5
#define ITEM_SIZE sizeof(int)

QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int xData = 100;
    while (1) {
        xQueueSend(xQueue, &xData, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void vReceiverTask(void *pvParameters) {
    int xReceivedData;
    while (1) {
        xQueueReceive(xQueue, &xReceivedData, portMAX_DELAY);
        // 处理接收到的数据
    }
}

int main() {
    xQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);

    xTaskCreate(vSenderTask, "Sender", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(vReceiverTask, "Receiver", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    vTaskStartScheduler();

    while (1) {
        // 该处不会被执行
    }
}

项目解释:

在这个示例中,我们首先创建了一个队列xQueue,其长度为5,每个项目的大小为一个int。然后我们创建了两个任务:vSenderTaskvReceiverTaskvSenderTask任务向队列发送数据,而vReceiverTask任务从队列接收数据。

vSenderTask任务中,我们使用xQueueSend()函数向队列发送数据。在vReceiverTask任务中,我们使用xQueueReceive()函数从队列接收数据,并可以在任务中处理接收到的数据。这两个任务都有一个无限循环,因此它们将一直运行。

main函数中,我们创建了两个任务,并启动了FreeRTOS调度器。一旦调度器启动,任务将开始执行其功能。

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

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

相关文章

泛型和Object的区别

什么时候使用 泛型:只要确定了用哪类对象,并且用到这个对象里的方法。选择泛型,泛型更加精确,只要用到Object的地方基本都能用泛型代替。Object类:Object是所有类的父类,更加笼统,且只能使用固…

找不到客户?交你一招

在当今社会中,获取潜在客户的信息对于企业的成功至关重要。然而,许多企业却面临着找不到潜在客户的难题。 企业想要成交的第一步就是寻找客户,将产品和目标客户进行匹配才能提高成交率。 因此企业首先需要明确自己的目标客户群体&#xff0…

GAN:WGAN-DIV

论文:https://arxiv.org/pdf/1712.01026.pdf 代码: 发表:2018 摘要 在计算机视觉的许多领域中,生成对抗性网络已经取得了巨大的成功,其中WGANs系列被认为是最先进的,主要是由于其理论贡献和竞争的定性表…

Leetcode—538.把二叉搜索树转换为累加树【中等】

2023每日刷题(四十九) Leetcode—538.把二叉搜索树转换为累加树 实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(…

Node包管理工具 - nvm、npm、yarn、cnpm、pnpm

转载说明 原文地址 简介 nvm : 可以实现一台电脑,拥有多个版本的Node npm : node package manager 下载Node后自带的一个包管理工具 yarn : npm 的升级版,更优秀 cnpm : 配置下载非官方地址的依赖(淘宝、华为、腾讯镜像) pnpm :…

Java jdk和jre的区别

jdk和jre的区别为:JRE是java运行时环境而JDK是java开发工具包,JDK包含JRE,但是JRE可以独立安装。 JDK: java development kit (java开发工具),JDK 是用于开发 Java 程序的最小环境。 JRE: java runtime e…

视频推拉流直播点播EasyDSS平台点播文件加密存储的实现方法

视频推拉流直播点播系统EasyDSS平台,可提供流畅的视频直播、点播、视频推拉流、转码、管理、分发、录像、检索、时移回看等功能,可兼容多操作系统,还能支持CDN转推,具备较强的可拓展性与灵活性,在直播点播领域具有广泛…

uniapp实现拨打电话跳转手机拨号界面 (ios和安卓通用)

效果展示:左边为安卓系统展示,右边为ios系统展示 代码: toPhone(){uni.makePhoneCall({phoneNumber: "10086", //要拨打的手机号success: (res) > {// console.log("调用成功")},fail: (res) > {// console.log(调…

Web安全-初识SQL注入(一)

1、初识SQL注入 1.1、什么是注入? 将不受信任的数据作为命令或查询的一部分发送到解析器时,会产生诸如SQL注入、NoSQL注入、OS 注入和LDAP注入的注入缺陷。攻击者的恶意数据可以诱使解析器在没有适当授权的情况下执行非预期命令或访问数据。 注入能导…

JOSEF约瑟 同步检查继电器DT-13/200 100V柜内安装,板前接线

系列型号 DT-13/200同步检查继电器; DT-13/160同步检查继电器; DT-13/130同步检查继电器; DT-13/120同步检查继电器; DT-13/90同步检查继电器; DT-13/254同步检查继电器; 同步检查继电器DT-13/200 100V柜内板前接线 一、用途 DT-13型同步检查继电器用于两端供电线路的…

构建高效预约系统:预约系统源码的设计与实现

随着社会的不断进步,预约系统在各个领域的应用愈发广泛。为了满足不同行业的需求,设计高效的预约系统源码至关重要。在本文中,我们将深入研究预约系统的设计原则,并提供一些关键的技术代码示例,帮助读者更好地理解如何…

怎么使用AI写作工具批量写作?批量AI智能写作的方法

随着科技的不断发展,人工智能(AI)技术在各个领域都有了广泛的应用,其中之一就是智能写作。对于需要大量文本创作的用户来说,批量AI智能写作成为提高效率的一项重要工具。本文将专心分享批量AI智能写作的方法、工具以及…

分享116个图片JS特效,总有一款适合您

分享116个图片JS特效,总有一款适合您 116个图片JS特效下载链接:https://pan.baidu.com/s/1WvUvmG1adR2EJG97MiGj3A?pwd6666 提取码:6666 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整…

t-SNE方法:

使用t-SNE时,除了指定你想要降维的维度(参数n_components),另一个重要的参数是困惑度(Perplexity,参数perplexity) 困惑度: 困惑度大致表示如何在局部或者全局位面上平衡关注点&am…

【稳定检索|投稿优惠】2024年光电信息与机器人发展国际会议(ICOIRD 2024)

2024年光电信息与机器人发展国际会议(ICOIRD 2024) 2024 International Conference on Optoelectronic Information and Robot Development(ICOIRD 2024) 一、【会议简介】 信息技术与人工智能的浪潮正在激荡,不断刷新我们生活的页面,深刻烙印在光电信息…

西安安泰Aigtek——ATA-8152射频功率放大器

ATA-8152射频功率放大器简介 ATA-8152是一款射频功率放大器。其P1dB输出功率100W,饱和输出功率200W。增益数控可调,一键保存设置,提供了方便简洁的操作选择,可与主流的信号发生器配套使用,实现射频信号的放大。宽范围供…

【每日一题】到达首都的最少油耗

文章目录 Tag题目来源题目解读解题思路方法一:贪心深搜 写在最后 Tag 【递归/深度优先搜索】【树】【2023-12-05】 题目来源 2477. 到达首都的最少油耗 题目解读 每个城市都有一位代表需要前往城市 0 进行开会。每个城市都有一辆座位数为 seats 的汽车&#xff0…

高温老化房稳定性、应用领域

高温老化房控制系统的稳定性主要有四点: 1. 温度控制:控制系统确保老化室内的温度在整个老化试验过程中保持稳定并在期望的范围内。这种稳定性对于准确可靠的测试结果至关重要。 2. 湿度控制:控制系统同时保持老化室内湿度水平稳定。这一点很重要,因为某些材料或产…

gitlab高级功能之mirroring - pull mirroring(二)

上一篇详细介绍了mirroring的push功能,本篇给大家介绍下mirroring的pull功能的使用。 文章目录 1. pull mirroring1.1 介绍1.2 工作方式 2. 配置拉取镜像2.1 基于https的方式step1: 选择远程gitlab所在的项目和获取tokenstep2: 配置本地gitlabstep3: 验证 2.2 基于s…

大文本限制录入文字后通过输入法鼠标单击还可继续超限额录入问题

textInpEl.on(keyup propertychange, "textarea", function () { var realMaxLength $(this).parent().parent().find(".maxNum").text(); //真实的最大长度 var endFontLen $(this).val().length; if (endFontLen < rea…