文章目录
- 1、基本概念(队列实际上就是一个结构体,可以理解为就是一个数组)
- 2、使用场景:任务间或任务与中断间传递数据
- 3、使用队列的好处
- (1)休眠唤醒
- (2)提高CPU利用率
- 4、队列的核心
- 5、动态创建队列——xQueueCreate()
- 6、队列删除函数—— vQueueDelete()
- 7、读队列
- (1)读队列流程示意图
- (2)API函数——xQueueReceive()与xQueueReceiveFromISR()
- 8、写队列
- (1)写队列流程
- (2)API函数
- 1)向队尾写入数据
- 2)向队头写入数据
- 9、查询队列
- 10、复位队列
1、基本概念(队列实际上就是一个结构体,可以理解为就是一个数组)
队列:即消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息。
即在任务或中断服务程序都可以对队列进行操作。
通过消息队列服务,任务或者中断服务例程可以将一条或多条消息放入队列中;同样一个或多个任务可以从消息队列中获得消息。
支持先进先出原则,也支持后进先出原则。
2、使用场景:任务间或任务与中断间传递数据
3、使用队列的好处
(1)休眠唤醒
任务进行休眠时会执行两步:改变状态和队列链表记录这个任务,具体如下所示:
(2)提高CPU利用率
即在使用队列后,拥有了休眠唤醒功能,不须像裸机程序一样不断地去查询是否有数据存在等,从而使CPU能够利用这段时间去做一些更加必要的事情。
4、队列的核心
关中断(来实现互斥)
环形缓存区(即一个数组,存放满了之后再从头开始存放,来保存数据)
链表(记录谁在等待队列,来实现休眠和唤醒)
队列的链表可分为两个,一个是等待读的链表,另一个是等待写的链表(如下所示)
List_t xTasksWaitingToSend;
List_t xTasksWaitingToReceive;
5、动态创建队列——xQueueCreate()
例如:
xQueue = xQueueCreate( 5 , sizeof(int32_t) )
表示创建了一个长度为5、数据大小为4字节的队列。
以前面举例来说,其队列的空间大小是buff的大小加上头部(队列控制块)的大小,而buff的大小为5*4=20个字节。
当消息队列被创建时,系统会为队列控制块分配对应的内存空间,用于保存消息队列的一些信息如消息的存储位置,头指针 pcHead、尾指针 pcTail、消息大小 uxItemSize 以及队列长度 uxLength,以及当前队列消息个数uxMessagesWaiting 等。
6、队列删除函数—— vQueueDelete()
传输进去的实参是要删除队列的句柄。
7、读队列
(1)读队列流程示意图
(2)API函数——xQueueReceive()与xQueueReceiveFromISR()
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
void *pvBuffer,
BaseType_t *pxTaskWoken);
8、写队列
(1)写队列流程
(2)API函数
1)向队尾写入数据
/* 等同于 xQueueSendToBack
* 往队列尾部写入数据,如果没有空间,阻塞时间为 xTicksToWait
*/
BaseType_t xQueueSend(QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait );
/*
* 往队列尾部写入数据,如果没有空间,阻塞时间为 xTicksToWait
*/
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait);
/*
* 往队列尾部写入数据,此函数可以在中断函数中使用,不可阻塞
*/
BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,
const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken );
2)向队头写入数据
/*
* 往队列头部写入数据,如果没有空间,阻塞时间为 xTicksToWait
*/
BaseType_t xQueueSendToFront( QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait );
/*
* 往队列头部写入数据,此函数可以在中断函数中使用,不可阻塞
*/
BaseType_t xQueueSendToFrontFromISR( QueueHandle_t xQueue,
const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken);
9、查询队列
返回队列中可用数据的个数
*/
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
/*
* 返回队列中可用空间的个数
*/
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
10、复位队列
/* pxQueue : 复位哪个队列;
* 返回值: pdPASS(必定成功)
*/
BaseType_t xQueueReset( QueueHandle_t pxQueue);