目录
1.队列集简介
一个队列只允许任务间传递的消息为同一种数据类型
如果需要在任务间传递不同数据类型的消息时(队列、信号量、事件标志等), 那么就可以使用队列集 !
作用:用于对多个队列或信号量进行“监听”,其中不管哪一个消息到来,都可让任务退出阻塞状态然后通过用 if 判断返回的句柄来判断是哪个来消息了,再进行后续操作

2.队列集相关API函数介绍
队列集使用流程:
- 启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为 1
- 创建队列集
- 创建队列或信号量
- 往队列集中添加队列或信号量
- 往队列发送信息或释放信号量
- 获取队列集的消息

2.1 创建队列集
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );
形参:uxEventQueueLength (队列集可容纳的队列数量)
返回值:NULL (队列集创建失败)其他值(队列集创建成功,返回队列集句柄)
2.2 往队列集中添加队列
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet);
形参:xQueueOrSemaphore (待添加的队列句柄)
xQueueSet (队列集)
返回值:pdPASS (队列集添加队列成功)pdFAIL (队列集添加队列失败)
此函数用于往队列集中添加队列,要注意的时,队列在被添加到队列集之前,队列中不能有有效的消息
2.3 移除队列集
BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet);
形参:xQueueOrSemaphore (待移除的队列句柄)
xQueueSet (队列集)
返回值:pdPASS (队列集移除队列成功)pdFAIL (队列集移除队列失败)
此函数用于从队列集中移除队列, 要注意的是,队列在从队列集移除之前,必须没有有效的消息
2.4 获取队列集中有效消息的队列
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet);
形参:xQueueSet (队列集)
xTicksToWait (阻塞超时时间)
返回值:NULL (获取消息失败)其他值(获取到消息的队列句柄)
3.队列集操作实验
实验设计:将设计三个任务:start_task、task1、task2
start_task:用来创建其它任务,并创建队列集,队列/信号量,将队列/信号量添加到队列集中
task1:用于扫描按键,当KEY0按下,往队列写入数据,当KEY1按下,释放二值信号量
task2:读取队列集中的消息,并打印
代码如下:
SemaphoreHandle_t Semhore_Handle;
QueueHandle_t Queue_Handle;
QueueSetHandle_t QueueSet_Handle;
...
其他代码不展示
...
/*start_task 创建队列、二值信号量、队列集和其他任务*/
void start_task(void *pvParameters)
{
BaseType_t err1 = 0;
BaseType_t err2 = 0;
/*创建队列*/
Queue_Handle = xQueueCreate (2, sizeof(uint8_t));
if(Queue_Handle == NULL)
{
printf("队列创建失败\r\n");
}else
{
printf("队列创建成功\r\n");
}
/*创建二值信号量*/
Semhore_Handle = xSemaphoreCreateBinary();
if(Semhore_Handle == NULL)
{
printf("二值信号量创建失败\r\n");
}else
{
printf("二值信号量创建成功\r\n");
}
/*创建队列集*/
QueueSet_Handle = xQueueCreateSet(2);
if(QueueSet_Handle == NULL)
{
printf("队列集创建失败\r\n");
}else
{
printf("队列集创建成功\r\n");
}
/*添加队列进入队列集*/
err1 = xQueueAddToSet(Queue_Handle, QueueSet_Handle);
if(err1 == pdTRUE)
{
printf("队列加入队列集\r\n");
}
/*添加二值信号量进入队列集*/
err2 = xQueueAddToSet(Semhore_Handle, QueueSet_Handle);
if(err2 == pdTRUE)
{
printf("二值信号量加入队列集\r\n");
}
taskENTER_CRITICAL(); /*进入临界区*/
xTaskCreate( (TaskFunction_t ) task1,
(char * ) "task1",
(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t * ) &task1_handler );
xTaskCreate( (TaskFunction_t ) task2,
(char * ) "task2",
(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t * ) &task2_handler );
vTaskDelete(start_task_handler);
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/*task1 写入队列和释放二值信号量*/
void task1(void *pvParameters)
{
BaseType_t err1 = 0;
BaseType_t err2 = 0;
uint8_t Key = 0;
while(1)
{
Key = key_scan(0);
if(Key == KEY2_PRES)
{
err1 = xQueueSend(Queue_Handle, &Key, portMAX_DELAY);
if(err1 == pdPASS)
{
printf("队列写入消息成功\r\n");
}
}
if(Key == WKUP_PRES)
{
err2 = xSemaphoreGive(Semhore_Handle);
if(err2 == pdPASS)
{
printf("二值信号量释放成功\r\n");
}
}
}
}
/*task2 读取队列和获取二值信号量*/
void task2(void *pvParameters)
{
uint8_t Key = 0;
uint8_t err1;
uint8_t err2;
QueueSetMemberHandle_t QueueSetMember_Handle;
while(1)
{
QueueSetMember_Handle = xQueueSelectFromSet(QueueSet_Handle, portMAX_DELAY);
if(QueueSetMember_Handle == Queue_Handle)
{
err1 = xQueueReceive( Queue_Handle, &Key, portMAX_DELAY);
if(err1 == pdTRUE)
{
printf("读取队列消息成功:%d\r\n", Key);
}
}
if(QueueSetMember_Handle == Semhore_Handle)
{
err2 = xSemaphoreTake(Semhore_Handle, portMAX_DELAY);
{
if(err2 == pdTRUE)
{
printf("获取二值信号量成功\r\n");
}
}
}
}
}
现象:只有按键按下,无论是写入队列还是释放信号量,都可以唤醒获取信息的任务,并通过判断返回的句柄,从而获取消息。

1229

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



