文章目录
- 前言
- 一、为什么需要队列集
- 二、队列集的基本操作顺序
- 三、使用方法
- 3.1 创建队列集
- 3.2 与队列集建立联系
- 3.3 读取队列集得到有数据的队列
- 3.4 示例代码
- 总结
前言
FreeRTOS是一个开源的实时操作系统内核,广泛应用于嵌入式系统中。它提供了一套丰富的功能,其中队列是一个重要的组件,用于实现任务之间的通信和数据传递。本文将重点介绍FreeRTOS中的队列集(Queue Set)的基础知识,以帮助初学者更好地理解和应用这一功能。
在嵌入式系统中,多个任务可能需要共享数据或进行协同工作。队列集是FreeRTOS中用于处理这种情况的一种高效机制。通过使用队列集,任务可以等待多个队列中的任何一个,从而更灵活地响应事件和共享信息。在本文中,我们将深入探讨队列集的概念、使用方法以及在实际应用中的一些典型场景。
一、为什么需要队列集
比如说,你的系统有鼠标,键盘,触摸屏等等等等,这些输入设备都需要往app里面发送数据,那么发送数据肯定就是使用队列了,他们每一个都需要一个独一无二的队列进行存储对应的数据,但是我们之前学的队列,他每次等待都只能等待某一个队列,但是现在有几个了,所以这样就不行。所以freertos引入了队列集。队列集其实就是保存了一堆队列的队列而已。队列集里面任意一个有数据,就会唤醒等待队列的任务,任务来取出相应的数据即可。
二、队列集的基本操作顺序
首先我们的队列集也是一个队列,他存着比如触摸,鼠标等等的队列。
- 首先我们要使用队列集需要先创建一个队列集,如果要检测3个队列A、B、C,这个队列集的长度为A+B+C队列的长度
- 与你需要检测的队列建立联系。在queue中里面有个handle指向队列集
- 当比如触摸屏有数据,他把数据放到他的队列里面去,然后需要把触摸屏队列handle放到队列集中
- 我们可以去读queue set,他会返回某一个队列(一次)
- 读返回的队列数据即可(一次)
三、使用方法
如果我们想使用队列集,需要把这个宏设置为1:configUSE_QUEUE_SETS
我们这边以一个示例来讲解,这个示例为task1和task2填数据到各自的队列,然后task3来读队列集
3.1 创建队列集
我们可以使用下面这个函数来创建一个队列集
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );
参数为队列集的长度。如果要检测3个队列A、B、C,这个队列集的长度为A+B+C队列的长度
返回值为队列集的handle
3.2 与队列集建立联系
我们可以使用下面这个函数用来队列和队列集建立联系
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
参数1为Queue的handle,参数2为与哪个队列集联系
3.3 读取队列集得到有数据的队列
我们可以使用下面这个函数进行队列集的读取:
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait );
参数1为哪个队列集,参数2为等待时间
返回值为有数据的队列.
然后我们就可以使用队列的读函数直接去读了,可以不需要等待时间,因为前面都判断了一定有数据,所以不需要等待。
3.4 示例代码
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#define QUEUE_LENGTH 5
#define ITEM_SIZE sizeof(int)
// 声明队列句柄
QueueHandle_t queue1, queue2;
// Task1,向队列1发送数据
void Task1(void *pvParameters) {
int data = 1;
while (1) {
// 向队列1发送数据
xQueueSend(queue1, &data, portMAX_DELAY);
data++; // 更新数据
vTaskDelay(pdMS_TO_TICKS(1000)); // 1秒延迟
}
}
// Task2,向队列2发送数据
void Task2(void *pvParameters) {
int data = 100;
while (1) {
// 向队列2发送数据
xQueueSend(queue2, &data, portMAX_DELAY);
data += 100; // 更新数据
vTaskDelay(pdMS_TO_TICKS(2000)); // 2秒延迟
}
}
// Task3,从队列集中读取数据
void Task3(void *pvParameters) {
QueueSetHandle_t queueSet;
QueueHandle_t member;
BaseType_t xResult;
int received_data;
// 创建队列集
queueSet = xQueueCreateSet(QUEUE_LENGTH * 2);
// 将队列1和队列2添加到队列集中
xQueueAddToSet(queue1, queueSet);
xQueueAddToSet(queue2, queueSet);
while (1) {
// 等待从队列集中读取数据
member = xQueueSelectFromSet(queueSet, portMAX_DELAY);
// 判断是哪个队列有可读数据
if (member == queue1) {
// 从队列1中接收数据
xQueueReceive(queue1, &received_data, 0);
printf("Task3 received data from queue1: %d\n", received_data);
} else if (member == queue2) {
// 从队列2中接收数据
xQueueReceive(queue2, &received_data, 0);
printf("Task3 received data from queue2: %d\n", received_data);
}
}
}
int main(void) {
// 创建队列
queue1 = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);
queue2 = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);
// 创建任务
xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(Task3, "Task3", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
// 启动调度器
vTaskStartScheduler();
return 0;
}
总结
队列集作为FreeRTOS的一个重要特性,在嵌入式系统的开发中发挥着关键作用。通过学习队列集的基础知识,开发者可以更好地设计和实现任务之间的通信机制,提高系统的灵活性和效率。在实际应用中,合理使用队列集可以简化任务之间的同步与通信,使系统更加可靠和稳定。希望本文能够为初学者提供一个清晰的入门指南,让大家更好地利用FreeRTOS的队列集功能进行嵌入式