首页 > 其他分享 >【Freertos基础入门】队列(queue)的使用

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

时间:2023-08-19 13:00:34浏览次数:29  
标签:QueueHandle 函数 Freertos BaseType 队列 void queue xQueue

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

@TOC


前言

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

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


一、队列是什么?

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

【Freertos基础入门】队列(queue)的使用_数据项

二、队列的操作

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中一种有用的通信机制,可用于在任务之间传递数据。通过使用队列,我们可以实现任务之间的数据共享和同步。在使用队列时,需要注意队列的深度和每个数据项的大小,并选择适当的阻塞等待时间以避免资源争用和任务饥饿等问题。 在后面我们还将介绍到信号量,互斥锁,任务通知等任务的通信机制,他们都是为了解决任务的通信研究出来的技术和算法。

标签:QueueHandle,函数,Freertos,BaseType,队列,void,queue,xQueue
From: https://blog.51cto.com/u_16176403/7148946

相关文章

  • 深入理解后端开发中的消息队列与异步处理
    在现代的应用开发中,消息队列和异步处理已成为构建高性能、可伸缩的后端系统的重要工具。本文将深入探讨消息队列的原理、优势,以及如何在后端开发中应用消息队列和异步处理。什么是消息队列?消息队列是一种将消息从一个应用传递到另一个应用的通信方式。它具有以下特点:解耦:消息队列可......
  • 构建高效可靠的后端服务:使用消息队列和异步处理
    在现代应用开发中,构建高效可靠的后端服务是至关重要的。本文将深入探讨如何使用消息队列和异步处理来优化后端服务,实现高性能和可扩展性。为什么使用消息队列和异步处理?消息队列是一种用于在应用程序之间传递消息的机制,而异步处理是一种执行任务的方式,它不会阻塞主要的应用程序流程......
  • 队列
    队列:只有两个口进出数据,一个专门进入数据,另一个专门出数据,先进先出,FIFO表1. 顺序队列:数据项:存储元素的连续内存的首地址容量队头位置  (出队)队尾位置  (入队)[元素数量]运算:创建、销毁、清空、出队、入队、队空、队满、队头、队尾、元素数量需要注意的问题1......
  • day10 - 栈与队列part01
    232. 用栈实现队列详解classMyQueue{public:stack<int>st_in;stack<int>st_out;MyQueue(){}voidpush(intx){st_in.push(x);}intpop(){if(st_out.empty()){while(!st_in.empt......
  • 关于云原生开源开发者沙龙「微服务X消息队列专场」的延期通知
    作者:微服务X消息队列各位报名参会的同学,大家好:非常感谢大家对本期云原生开源开发者沙龙「微服务X消息队列专场」的关注与支持。因故原定于8月12日(周六)举办的沙龙延期举行。具体时间和举办地点如下:阿里云云原生开源开发者沙龙微服务X消息队列专场深圳站,推迟于8月27日(......
  • Redis 过期监听 + 加阻塞队列
    https://redis.io/docs/manual/keyspace-notifications/ 简单一句话就是要订阅key失效事件 应用场景:在线客服中开启会话后,如果客户一段时间未回复,则结束会话。为了保证会话结束的时效性,通过redis订阅key失效事件处理        配置notify-keyspace-eventsE......
  • 栈与队列
    栈与队列前言 栈与队列作为线性表结构的代表,在计算机领域应用广泛。我们耳熟能详的系统栈,进程处理等计算机操作系统底层实现原理都是间接或者直接使用了相关数据结构或其思想,下面让我们来介绍这两种数据结构。栈结构定义  栈(stack)是限定仅在表尾进行插入或者删除的线性......
  • P9518 queue 题解
    题目传送门思路一道稍稍有点复杂的模拟好题。本题的关键性就在于需要实现的leave函数必须支持任意位置的删除,任意元素的查询,这对于queue或是deque是十分不利的。故本题使用另外一种STL:list实现。但是,list的查询其实也是比较耗费时间的,那么我们可以使用\(Map\)来......
  • 关于 SAP ABAP Enqueue Function Module 的输入参数 _wait
    我们查看ABAP系统根据LockObject自动生成的EnqueueFunctionModule,可以发现它有一个名叫_wait的输入参数,默认值为space:该参数决定了发生锁冲突时的锁行为。开发人员有以下选择:初始值:如果由于存在竞争锁而导致锁定尝试失败,则会触发异常FOREIGN_LOCK。X:如果由......
  • 队列的实现方式(先进先出 FIFO)--环形队列
    博客地址:https://www.cnblogs.com/zylyehuo/#-*-coding:utf-8-*-classQueue:def__init__(self,size=100):self.queue=[0for_inrange(size)]self.size=sizeself.rear=0#队尾指针self.front=0#队首指针......