一、队列集简介
队列只能传输同一种数据,不同的任务之间需要传输不同的数据类型的消息时那么就需要使用队列集。
作用:用于对多个队列或者信号量进行监听,其中不管任何一个到来,都可以使任务退出阻塞状态。
假设:有个接受任务,使用到队列接收和信号量的获取,如下:
二、相关API函数
队列集使用流程:
1、启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为 1;
2、创建队列集;
3、创建队列或信号量;
4、往队列集中添加队列或信号量;
5、往队列发送信息或释放信号量;
6、获取队列集的消息;
创建队列集函数:QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );
往队列集中添加队列,需要注意的时,队列再被添加到队列集之前,队列中不能有有效的消息:
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore , QueueSetHandle_t xQueueSet );
往队列集中移除队列,需要注意的时,队列在从队列集移除之前,队列中不能有有效的消息:
BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore , QueueSetHandle_t xQueueSet );
此函数用于在任务中获取队列集中有有效消息的队列:
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait );
三、队列集操作实验
工程代码:
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <stdio.h>
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_TASK_STACK_SIZE 128
//任务句柄
TaskHandle_t start_task_handler;
//开始任务
void start_task(void *pvParameters);
//任务优先级
#define TASK1_PRIO 2
//任务堆栈大小
#define TASK1_STACK_SIZE 128
//任务句柄
TaskHandle_t task1_handler;
//LED0任务
void task1(void *pvParameters);
//任务优先级
#define TASK2_PRIO 3
//任务堆栈大小
#define TASK2_STACK_SIZE 128
//任务句柄
TaskHandle_t task2_handler;
//LED1任务
void task2(void *pvParameters);
QueueSetHandle_t queueset_handle;
QueueHandle_t queue_handle;
QueueHandle_t semaphore_handle;
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
GPIO_INIT();
KEY_INIT();
uart_init(9600);
//创建开始任务
xTaskCreate( (TaskFunction_t ) start_task, //任务函数指针
(char * ) "start_task", //任务函数名称
(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE, //任务堆栈大小
(void * ) NULL, //传递给任务函数的参数(一般为空)
(UBaseType_t ) START_TASK_PRIO, //任务优先级
(TaskHandle_t * ) &start_task_handler ); //任务句柄
//开启任务调度
vTaskStartScheduler();
}
开始任务函数
void start_task(void *pvParameters)
{
queueset_handle = xQueueCreateSet(2); //创建队列集,可以存放2个队列
if(queueset_handle != NULL)
{
printf("队列集创建成功\r\n");
}
queue_handle = xQueueCreate(1,sizeof(uint8_t)); //创建队列
semaphore_handle = xSemaphoreCreateBinary(); //创建二值信号量
xQueueAddToSet(queue_handle,queueset_handle);
xQueueAddToSet(semaphore_handle,queueset_handle);
//创建LED0任务
xTaskCreate( (TaskFunction_t ) task1,
(char * ) "task1",
(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t * ) &task1_handler );
//创建LED1任务
xTaskCreate( (TaskFunction_t ) task2,
(char * ) "task2",
(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t * ) &task2_handler );
//删除自己
vTaskDelete(NULL);
}
//任务一释放二值信号量
void task1(void *pvParameters)
{
u8 key = 0;
BaseType_t err = 0;
while(1)
{
key = KEY_SCAN(0);
if(key == KEY0_PRES)
{
err = xQueueSend(queue_handle,&key,portMAX_DELAY);
if(err == pdPASS)
{
printf("往队列queue_handle写入数据成功!!\r\n");
}
}else if(key == KEY1_PRES)
{
err = xSemaphoreGive(semaphore_handle);
if(err == pdPASS)
{
printf("释放信号量成功!!\r\n");
}
}
vTaskDelay(10);
}
}
/* 任务二,获取队列集的消息 */
void task2( void * pvParameters )
{
QueueSetMemberHandle_t member_handle;
uint8_t key;
while(1)
{
member_handle = xQueueSelectFromSet( queueset_handle,portMAX_DELAY);
if(member_handle == queue_handle)
{
xQueueReceive( member_handle,&key,portMAX_DELAY);
printf("获取到的队列数据为:%d\r\n",key);
}else if(member_handle == semaphore_handle)
{
xSemaphoreTake( member_handle, portMAX_DELAY );
printf("获取信号量成功!!\r\n");
}
}
}