FreeRTOS 学习笔记>队列

embedded/2024/11/14 1:44:23/

FreeRTOS 中的队列是任务之间进行通信的一种重要机制。通过队列,任务可以发送和接收数据,从而实现同步和数据共享。

队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列中读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间xTicksToWait,在这段时间中,如果队列是空,该任务将保持阻塞状态以等待队列数据有效。当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息:当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。消息队列是一种异步的通信方式。

通过消息队列服务,任务或中断服务例程可以将一条或多条消息放入消息队列中,同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO),但是也支持后进先出原则(LIFO)。

队列的基本操作

  1. 创建队列: 使用 xQueueCreate() 函数可以创建一个队列。该函数需要两个参数:队列的长度和每个队列项的大小。

    QueueHandle_t xQueue = NULL;
    xQueue = xQueueCreate(10, sizeof(int));
    
  2. 发送数据到队列: 使用 xQueueSend()xQueueSendToBack() 函数可以将数据发送到队列中。这些函数需要队列句柄、要发送的数据和等待时间作为参数。

    xQueueSend()用于向队列尾部发送一个队列消息。消息以拷贝的形式入队,而不是以引用的形式。该函数不能在中断服务程序里面调用,中断中需使用带有中断保护功能的xQueueSendFromISR()代替。

    xQueueSendToFront()用于向队列队首发送一个消息。消息以拷贝的形式入队。该函数不能在中断服务程序里面调用,中断中需使用带有中断保护功能的xQueueSendToFrontFromISR()代替。

    int data = 100;
    xQueueSend(xQueue, &data, portMAX_DELAY);//中断中需使用此函数
    xQueueSendFromISR(xQueue, &data, portMAX_DELAY);
    
  3. 从队列接收数据: 使用 xQueueReceive() 函数可以从队列中接收数据。该函数需要队列句柄、接收缓冲区和等待时间作为参数。

    xQueueReceive()用于从一个队列中接收消息并把消息从队列中删除。接收的消息是以拷贝 的形式进行的,所以我们必须提供一个足够大空间的缓冲区。该函数绝不能在中断服务程序里面被调用,而是必须使用带有中断保护功能的 xQueueReceiveFromISR ()来代替。

    int receivedData;
    xQueueReceive(xQueue, &receivedData, portMAX_DELAY);
    

队列的应用场景

队列在 FreeRTOS 中有广泛的应用,例如:

  • 任务间通信:一个任务可以将数据发送到队列中,另一个任务可以从队列中接收数据,从而实现任务间的通信。
  • 中断处理:中断服务程序可以将数据发送到队列中,任务可以从队列中接收数据,从而实现中断处理与任务之间的通信。
  • 事件管理:通过队列可以实现事件的管理和处理,例如按键事件、传感器事件等。

通过合理使用队列,可以提高系统的响应性和数据处理效率。

队列的高级操作

  1. 队列的删除: 使用 vQueueDelete() 函数可以删除一个队列。删除队列后,所有试图访问该队列的任务都会收到错误。

    if (xQueue == NULL) {} else {vQueueDelete(xQueue);
    }
    
  2. 阻塞时间: 当队列为空时,xQueueReceive() 函数可以选择阻塞一段时间,等待队列中有数据可用。当队列已满时,xQueueSend() 函数也可以选择阻塞,直到队列有空位。

实战示例

假设我们有一个传感器任务,它定期读取传感器数据并将其发送到队列中。另一个任务负责从队列中读取数据并进行处理。

传感器任务

void vSensorTask(void *pvParameters) {int sensorData;for (;;) {// 读取传感器数据sensorData = readSensor();// 发送数据到队列xQueueSend(xQueue, &sensorData, portMAX_DELAY);// 延时一段时间vTaskDelay(pdMS_TO_TICKS(1000));}
}

数据处理任务

void vProcessingTask(void *pvParameters) {int receivedData;for (;;) {// 从队列接收数据if (xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdPASS) {// 处理接收到的数据processData(receivedData);}}
}

通过上述示例,我们可以看到如何通过队列在不同任务之间进行数据传输和处理,从而实现任务之间的协同工作。

欢迎指出博客中的错误,如果你觉得对你有用,记得点赞三连,有问题可留言,会及时回复


http://www.ppmy.cn/embedded/102319.html

相关文章

SpringCloud之一注册中心(Eureka)

一、Eureka概述 Eureka是Netflix公司开源的一个服务注册与发现的中间组件。 在微服务架构系统之中,我们经常提三个角色:注册中心 (Register)、服务提供者(Provider)、服务消费者(Consumer)。 1.注册中心:服务提供者可以将服务发布到注册中心…

C语言02 每日一练01

C语言02 每日一练01 习题一 对三个数进行从大到小的排序。习题二 计算1到100的和(两种方法)。习题三 判断100到200中的素数及其个数。 习题一 对三个数进行从大到小的排序。 对三个数进行从大到小的排序。 解题代码&#xff1a; #include <stdio.h>int main() {int a,…

JS中DOM详解【十大点】

JavaScript DOM 详解 JavaScript 中的 DOM&#xff08;文档对象模型&#xff09;是前端开发的重要知识点。它通过对象结构来表示 HTML 或 XML 文档&#xff0c;并提供对其内容进行操作的接口。本文将详细介绍 DOM 的基础知识、常用操作和事件处理等内容&#xff0c;确保全面且…

【Leetcode 2006 】 差的绝对值为 K 的数对数目 —— 哈希表

给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回数对 (i, j) 的数目&#xff0c;满足 i < j 且 |nums[i] - nums[j]| k 。 |x| 的值定义为&#xff1a; 如果 x > 0 &#xff0c;那么值为 x 。如果 x < 0 &#xff0c;那么值为 -x 。 示例 1&#xff1a;…

【C++】函数模板特化:深度解析与应用场景

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

代码随想录算法训练营_day25

题目信息 491. 非递减子序列 题目链接: https://leetcode.cn/problems/non-decreasing-subsequences/题目描述: 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可…

【R语言】基于nls函数的非线性拟合

非线性拟合 1.写在前面2.实现代码 1.写在前面 以下代码记录了立地指数的计算过程&#xff0c;包括了优势树筛选、误差清理、非线性拟合以及结果成图。 优势树木确定以及数据清理过程&#xff1a; 相关导向函数&#xff1a; 2.实现代码 ##*******************************…

CMake构建学习笔记8-OpenSceneGraph库的构建

1. 概论 在连续构建了zlib、libpng、libjpeg、libtiff、giflib以及freetype这几个库之后&#xff0c;接下来我们就要来一个大的&#xff0c;构建OpenSceneGraph这样大型库。OpenSceneGraph&#xff08;简称 OSG&#xff09;是一个高性能、跨平台的三维图形应用程序框架&#x…