【Freertos基础入门】队列(queue)的使用

简介: 【Freertos基础入门】队列(queue)的使用

前言


本系列基于stm32系列单片机来使用freerots

FreeRTOS是一个广泛使用的开源实时操作系统(RTOS),它提供了丰富的功能和特性,使嵌入式系统的开发更加简单和高效。队列是FreeRTOS中常用的一种通信机制,它用于在任务之间传递数据。


一、队列是什么?


队列是一种先进先出(FIFO)的数据结构,允许任务将数据项放入队列的末尾,并从队列的前端取出数据项。队列提供了一种线程安全的方式来实现任务之间的数据传输,尤其适用于生产者-消费者模式的应用。

7c49eb2d094c419f980812088cb56264.png


二、队列的操作


1. xQueueCreate():

函数原型: QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);

作用: 创建一个队列并返回队列的句柄。

参数:

uxQueueLength: 队列中的最大项数,即队列的深度。

uxItemSize: 单个队列项的大小(以字节为单位)。


2. xQueueCreate():

函数原型: BaseType_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait);

作用: 将一个数据项发送到队列中。

参数:

xQueue: 队列的句柄。

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

xTicksToWait: 阻塞等待的时间,如果队列已满,将会等待指定的时间,直到队列有空间可用。


3. xQueueReceive():

函数原型: BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

作用: 从队列中接收一个数据项。

参数:

xQueue: 队列的句柄。

pvBuffer: 接收数据项的缓冲区指针。

xTicksToWait: 阻塞等待的时间,如果队列为空,将会等待指定的时间,直到队列中有数据可用。


4. uxQueueMessagesWaiting():

函数原型: UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue);

作用: 获取队列中当前等待处理的数据项数量。

参数:

xQueue: 队列的句柄。


5. vQueueDelete():

vQueueDelete():

函数原型: void vQueueDelete(QueueHandle_t xQueue);

作用: 删除一个已创建的队列及其相关资源。

参数:

xQueue: 队列的句柄。


6.xQueueCreateStatic()

作用:静态分配queue内存

函数原型:QueueHandle_t xQueueCreateStatic( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t *pucQueueStorageBuffer, StaticQueue_t *pxQueueBuffer );

参数:uxQueueLength 队列长度,最多能存放多少个数据(item)

uxItemSize 每个数据(item)的大小:以字节为单位

pucQueueStorageBuffer

如果uxItemSize非0,pucQueueStorageBuffer必须指向一个

uint8_t数组,

此数组大小至少为"uxQueueLength * uxItemSize"

pxQueueBuffer 必须执行一个StaticQueue_t结构体,用来保存队列的数据结构

返回值 非0:成功,返回句柄,以后使用句柄来操作队列

NULL:失败,因为pxQueueBuffer为NULL


7.xQueueReset();

作用:队列刚被创建时,里面没有数据;使用过程中可以调用 xQueueReset() 把队列恢复为初始状态

函数原型:BaseType_t xQueueReset( QueueHandle_t pxQueue);参数为要复位的队列。


8.xQueueSendToBack()

函数原型:BaseType_t xQueueSendToBack( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );

作用:往队列尾部写入数据,如果没有空间,阻塞时间为xTicksToWait。

参数为要写的队列,数据,等待的时间


8.xQueueSendToBackFromISR()

函数原型:BaseType_t xQueueSendToBackFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );

作用:往队列尾部写入数据,此函数可以在中断函数中使用,不可阻塞


9.xQueueSendToFront()

作用:往队列头部写入数据,如果没有空间,阻塞时间为xTicksToWait

函数原型:BaseType_t xQueueSendToFront( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait );


10.xQueueSendToFrontFromISR()

作用:往队列头部写入数据,此函数可以在中断函数中使用,不可阻塞

函数原型:BaseType_t xQueueSendToFrontFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );


11.xQueueReceiveFromISR()

作用:读函数,此函数可以在中断内使用,不可阻塞

函数原型:BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken );

参数为要读的队列,存储的位置,一个指向 BaseType_t 变量的指针,在正常情况下被置为 pdFALSE。它用于通知内核是否有任务的优先级因为该操作而发生了改变。


12.uxQueueSpacesAvailable()
作用: 返回队列中可用空间的个数

函数原型:UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );

参数为要查询的队列


13.xQueueOverwrite()与xQueueOverwriteFromISR()

作用:当队列满时,这些函数会覆盖里面的数据,这也意为着这些函数不会被阻塞。

函数原型:

/* 覆盖队列
* xQueue: 写哪个队列
* pvItemToQueue: 数据地址
* 返回值: pdTRUE表示成功, pdFALSE表示失败
*/
BaseType_t xQueueOverwrite(
QueueHandle_t xQueue,
const void * pvItemToQueue
);
BaseType_t xQueueOverwriteFromISR(
QueueHandle_t xQueue,
const void * pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken
);


14.xQueuePeek()与xQueuePeekFromISR()函数

作用:偷看要取出队列的第二个元素

这些函数会从队列中复制出数据,但是不移除

数据。这也意味着,如果队列中没有数据,那么"偷看"时会导致阻塞;一旦队列中有数据以后每次"偷看"都会成功。

函数原型:

/* 偷看队列
* xQueue: 偷看哪个队列
* pvItemToQueue: 数据地址, 用来保存复制出来的数据
* xTicksToWait: 没有数据的话阻塞一会
* 返回值: pdTRUE表示成功, pdFALSE表示失败
*/
BaseType_t xQueuePeek(
QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait
);
BaseType_t xQueuePeekFromISR(
QueueHandle_t xQueue,
void *pvBuffer,
);


二、示例代码


下面是一个简单的示例代码,演示了如何使用FreeRTOS队列实现一个生产者任务和一个消费者任务之间的数据传输:

// 创建一个队列句柄
QueueHandle_t xQueue;
void vProducerTask(void *pvParameters) 
{
  int data = 0;
  while (1) {
  // 生产数据
  data = generateData();
      // 发送数据到队列
      if (xQueueSend(xQueue, &data, portMAX_DELAY) != pdPASS) 
      {
          // 处理发送失败的情况
      }
      // 延时,模拟生产速度
      vTaskDelay(pdMS_TO_TICKS(1000));
  }
}
void vConsumerTask(void *pvParameters) 
{
  int receivedData;
  while (1) 
  {
    // 从队列接收数据
    if (xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdPASS) {
    // 处理接收到的数据
    processData(receivedData);
    }
  }
}
int main() 
{
// 创建队列,队列长度为5,每个数据项的大小为sizeof(int)
xQueue = xQueueCreate(5, sizeof(int));
// 创建生产者任务
xTaskCreate(vProducerTask, "Producer", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
// 创建消费者任务
xTaskCreate(vConsumerTask, "Consumer", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
// 启动调度器
vTaskStartScheduler();
return 0;
}


总结


队列是FreeRTOS中一种有用的通信机制,可用于在任务之间传递数据。通过使用队列,我们可以实现任务之间的数据共享和同步。在使用队列时,需要注意队列的深度和每个数据项的大小,并选择适当的阻塞等待时间以避免资源争用和任务饥饿等问题。

在后面我们还将介绍到信号量,互斥锁,任务通知等任务的通信机制,他们都是为了解决任务的通信研究出来的技术和算法。

相关文章
|
7月前
|
设计模式 算法 C++
【C++初阶】12. Stack(栈)和Queue(队列)
【C++初阶】12. Stack(栈)和Queue(队列)
71 3
|
7月前
|
设计模式 存储 C++
C++初阶(十五)Stack和Queue
C++初阶(十五)Stack和Queue
69 0
|
传感器 调度 开发者
【Freertos基础入门】freertos任务的优先级
【Freertos基础入门】freertos任务的优先级
588 0
|
7月前
|
存储 小程序
【FreeRTOS】队列的使用
【FreeRTOS】队列的使用
|
7月前
|
存储 算法 Java
【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】
【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】
78 0
|
算法 索引 Python
数据结构与算法-(8)---队列(Queue)
数据结构与算法-(8)---队列(Queue)
71 1
|
7月前
|
API
FreeRTOS入门教程(队列详细使用示例)
FreeRTOS入门教程(队列详细使用示例)
254 0
|
7月前
|
存储 安全
FreeRTOS入门教程(队列的概念及相关函数介绍)
FreeRTOS入门教程(队列的概念及相关函数介绍)
113 0
|
7月前
|
存储 调度
FreeRTOS深入教程(队列内部机制和源码分析)
FreeRTOS深入教程(队列内部机制和源码分析)
176 0
|
数据采集 Python
Python多线程爬虫编程中queue.Queue和queue.SimpleQueue的区别和应用
在Python中,queue模块提供了多种队列类,用于在多线程编程中安全地交换信息。其中,queue.Queue 和queue.SimpleQueue 是两个常用的先进先出(FIFO)的队列类,它们有以下区别和优缺点: queue.Queue 是一个更复杂的队列类实现涉及到多个锁和条件变量,因此可能会影响性能和内存效率。 SimpleQueue 是一个更简单的队列类它只提供了put()和get()两个方法,并且不支持maxsize参数
221 0
Python多线程爬虫编程中queue.Queue和queue.SimpleQueue的区别和应用