FreeRTOS_队列(Queue)

1、 队列特性

队列(queue)可以用于"任务到任务"、“任务到中断”、"中断到任务"直接传输信息。

队列有如下特性:

  • 队列可以有若干个数据:
  • 每个数据的大小固定
  • 创建队列时指定队列的数据个数和数据大小
  • 队列的数据操作FIFO(先进先出)
  • 队列有自己的Buffer
  • 若数据太大可以发送数据地址

使用队列来传递数据可以在读写不成功(队列满了/空了)时使任务进入堵塞状态,提高CPU的运行效率。
当有多个任务等待读写队列时,优先级最高的任务会先进入就绪态;若多个任务的优先级相同,则等待最久的任务会优先进入就绪态。

2、队列函数

队列的使用流程:创建队列、写队列、读队列、删除队列

2.1、创建队列

队列的创建和任务的创建类似,分为动态分配内存静态分配内存

  • 动态分配内存:
QueueHandle_t xQueueCreate(
							  UBaseType_t uxQueueLength,
							  UBaseType_t uxItemSize
						  );
参数描述
uxQueueLength队列最多能存放的数据个数
uxItemSize给每个数据分配的内存大小(字节)
返回值非零:成功并返回句柄;null:内存不足,创建失败
  • 静态分配内存:分配给队列的内存需要提前创建好
QueueHandle_t xQueueCreateStatic(
							  UBaseType_t uxQueueLength,
							  UBaseType_t uxItemSize,
							  uint8_t *pucQueueStorageBuffer,
							  StaticQueue_t *pxQueueBuffer
						  );
参数描述
uxQueueLength队列最多能存放的数据个数
uxItemSize给每个数据分配的内存大小(字节)
pucQueueStorageBufferpucQueueStorageBuffer指向一个uint8_t数组
pxQueueBuffer执行一个StaticQueue_t结构体,用来保存队列的数据结构
返回值非零:成功并返回句柄;null:内存不足,创建失败

使用实例:

uint8_t ucQueueStorage[ QUEUE_LENGTH * sizeof(ITEM_SIZE)];//用来保存队列的数据
StaticQueue_t xQueueBuffer;//用来保存队列的结构体
QueueHandle_t xQueueHandle_1;//队列的句柄
void Task1(void *pvParam)
{
 xQueueHandle_1 = xQueueCreateStatic(QUEUE_LENGHT,
                                     ITEM_SIZE,
                                     ucQueueStorage,
                                     &xQueueBuffer);
}

2.2、写队列

写队列的函数有两套,在任务中使用、在ISR中使用。
中断只能使用以 “FromISR” 结尾的 API 函数。

//往队列的尾部写入数据
BaseType_t xQueueSend(
							  QueueHandle_t xQueue,
							  const void * pvItemToQueue,
							  TickType_t xTicksToWait
						 );
BaseType_t xQueueSendFromISR(
									 QueueHandle_t xQueue,
									 const void *pvItemToQueue,
									 BaseType_t *pxHigherPriorityTaskWoken
								);

参数说明:

参数描述
xQueue队列句柄,要写哪个队列
pvItemToQueue数据指针,将这个数据的值写入队列
xTicksToWait如果队列已满,可以让任务进入阻塞态,xTicksToWait 表示阻塞时间。若设为0,则会直接返回;若设为portMAX_DELAY,则一直等待到有空间可写
pxHigherPriorityTaskWoken如果入队导致一个任务解锁,并且解锁的任务优先级高于当前被中断的任务。如果将*pxHigherPriorityTaskWoken 设置成 pdTRUE,则在中断退出前需要进行一次上下文切换 ,去执行被唤醒的优先级更高的任务。
返回值pdPASS:数据成功写入了队列 errQUEUE_FULL:写入失败,因为队列满了且阻塞时间到了

举例:

BaseType_t xHigherPriorityTaskWoken =pdFALSE;
xQueueSendFromISR(g_xQueueRotary,&rdata,&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//若为pdTRUE,启动任务调度。   

2.3、读队列

BaseType_t xQueueReceive( QueueHandle_t xQueue, 
                          void * const pvBuffer,
                          TickType_t xTicksToWait );
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
                                 void * const pvBuffer, 
                                 BaseType_t * const pxHigherPriorityTaskWoken );

参数说明:

参数描述
xQueue队列句柄,要读哪个队列
pvBufferBuffer指针,将队列里的值写入此Buffer
xTicksToWait如果队列空则无法读出数据,可以让任务进入阻塞状态。 xTicksToWait表示阻塞的最大时间(Tick Count)。若设为0,则会直接返回;若设为portMAX_DELAY,则一直等待到有数据可读
pxHigherPriorityTaskWoken如果读队列导致一个任务解锁,并且解锁的任务优先级高于当前被中断的任务。如果将*pxHigherPriorityTaskWoken 设置成 pdTRUE,则在中断退出前需要进行一次上下文切换 ,去执行被唤醒的优先级更高的任务。
返回值pdTRUE:接收成功 pdFALSE:接收失败

2.4、重置队列

BaseType_t xQueueReset(QueueHandle_t pxQueue);
参数描述
pxQueue队列句柄,表示要重置的队列
返回值pdPASS:重置成功

此函数用于清空队列内的数据,从而使队列恢复至初始状态。

2.5、删除队列

void vQueueDelete( QueueHandle_t xQueue );
参数描述
pxQueue队列句柄,表示要删除的队列

此函数用于删除使用动态方法创建的队列,它会释放回收资源并避免内存泄漏。

3、队列集

队列集适用于多个发送者、多种数据(信号)类型向同一个接收者发送数据(信号)的情况。
队列集中可以包含队列和一些信号量。通过队列集,可以实现一个任务监听多个通信组件,从多个通信组件获取信号和数据的功能。

3.1、队列集创建

QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
参数描述
uxEventQueueLength队列集长度,最多能存放多少个数据(队列句柄)
返回值成功:返回句柄 失败:NULL ,内存不足

3.2、添加队列到队列集

BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
                               QueueSetHandle_t xQueueSet );
参数描述
xQueueOrSemaphore待添加的dui’leiduilei句柄
xQueueSet队列集的句柄
返回值成功:pdTRUE 失败:pdFALSE

3.3、读队列集

QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
                                                TickType_t const xTicksToWait );
参数描述
xQueueSet队列集的句柄
xTicksToWait阻塞时间,0~portMAX_DELAY
返回值成功:读出队列句柄 失败:NULL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值