一、队列
1、队列的特点
数据的操作采用先进先出的方法(FIFO),写数据时放到尾部,读数据时从头部开始读取。
也可以强制写队列头部,但不会覆盖头部数据。
队列中每个数据的大小时固定的。
创建队列时要指定长度,数据大小。
2、队列的使用

在创建队列时,会创建两个链表,分别存放等待数据的任务和等待向队列中写的数据,buf中存放队列的数据。
1)创建队列
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
//uxQueueLength 队列长度
//uxItemSize 每个项大小
可以看到xQueueXCreat()最后调用的是xQueueGenericCreate()。
创建队列时,会创建几个指针,pcHead始终指向头部,不会移动;pcWriteto在初始化时指向头部,后面指向要写入的下一个位置;pcReadFrom指向上一次读的位置,使用前要指向这一次读的位置。
2)向队列中写入数据
//向队列中写数据
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//向队列尾部写数据
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
//向队列首部写数据
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
//向队列尾部写数据,可以在中断函数中使用,不可阻塞
#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
//向队列头部写数据,可以在中断函数中使用,不可阻塞
#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
向队列中写数据,默认就是向队列尾部写数据;向队列头部写数据实际上是队列其他数据不变,然后写到pcReadFrom的位置,pcReadFrom向后移动一个位置,这样就写到了头部,下一次读取的就是这个数据。
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 )
4)查询
查询队列中有多少个数据,有多少剩余空间。
//返回队列中可用数据的个数
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
//返回队列中可用空间的个数
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
5)覆盖/偷看
当队列长度为1时,可以使用xQueueOverwrite()或xQueueOverwriteFromISR()来覆盖数据。队列长度必须为1,当队列满时,这些函数会覆盖里面的数据,这也意味着这些函数不会被阻塞。
#define xQueueOverwrite( xQueue, pvItemToQueue ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )
#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE )
偷看时不会移除数据,这些函数会从队列中复制出数据。这样意味着如果队列中没有数据,这些函数将会一直阻塞,一旦队列中有数据,每次偷看都会成功。
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
void * const pvBuffer )
3、队列集
顾名思义,队列集就是队列的集合,当接收程序想从多个队列中读取数据的时候,如果采用轮训的方式会导致效率低下,可以假设要从mouse,key,touch,三个队列中读取数据,当三个队列中某个队列由数据写入的时候,就会将其句柄放入到Queue_Set中,当从队列集中读取数据的时候,只需获取到其句柄,然后从其对应的队列中读取数据即可。
使用队列集的步骤如下:
//1.创建队列集
xQueueSet = xQueueCreateSet(4);
//2.添加联系
xQueueAddToSet(xQueueHandle1,xQueueSet);
xQueueAddTo

本文介绍了FreeRTOS中的队列、信号量、互斥量、事件组和任务通知。队列采用先进先出操作,有创建、读写等操作;信号量只传递状态;互斥量解决优先级继承问题;事件组用整数位表示事件;任务通知有简化版和专业版,各有特点和函数原型。
最低0.47元/天 解锁文章
892

被折叠的 条评论
为什么被折叠?



