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 | 给每个数据分配的内存大小(字节) |
pucQueueStorageBuffer | pucQueueStorageBuffer指向一个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 | 队列句柄,要读哪个队列 |
pvBuffer | Buffer指针,将队列里的值写入此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 |