队列集作用:
一个队列只允许任务之间传递的消息为同一种数据类型,队列集允许传递多种消息,且队列集能监听多个队列,不管哪个消息到来,都可以让任务退出阻塞状态
使用队列集的条件:在FreeRTOSConfig.h中把configUSE_QUEUE_SETS置1
创建队列集 xQueueCreateSet()
QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
参数:可容纳队列最大数量 返回值:失败 NULL,成功 队列集
参数:待添加的队列,队列集 返回值:成功 pdPASS,失败 pdFAIL
移除队列 xQueueRemoveFromSet()
BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,QueueSetHandle_t xQueueSet)
参数:待移除的队列,队列集 返回值:成功 pdPASS,失败 pdFAIL
获取队列集中有有效消息的队列 xQueueSelectFromSet()
QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet,TickType_t const xTicksToWait)
参数:队列集,阻塞超时时间(未获取成功便阻塞) 返回值:成功 目标队列,失败 NULL
队列集实验代码
//freertos_demo.c
#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/******************************************************************************************************/
/*FreeRTOS配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );
/******************************************************************************************************/
QueueSetHandle_t queueset_handle; //定义队列集变量
QueueHandle_t queue_handle; //定义队列
QueueHandle_t semphr_handle; //定义二值信号量队列
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
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 )
{
taskENTER_CRITICAL(); /* 进入临界区 */
queueset_handle = xQueueCreateSet( 2 ); /* 创建队列集,可以存放2个队列 */
if(queueset_handle != NULL)
{
printf("队列集创建成功!!\r\n");
}
queue_handle = xQueueCreate( 1, sizeof(uint8_t) ); /* 创建队列 */
semphr_handle = xSemaphoreCreateBinary(); /* 创建二值信号量 */
xQueueAddToSet( queue_handle,queueset_handle); //队列添加进队列集
xQueueAddToSet( semphr_handle,queueset_handle); //二值信号量添加进队列集
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(NULL);
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/* 任务一,实现队列发送以及信号量释放 */
void task1( void * pvParameters )
{
uint8_t key = 0;
BaseType_t err = 0;
while(1)
{
key = key_scan(0); //把按键扫描的值赋给key
if(key == KEY0_PRES)
{
err = xQueueSend( queue_handle, &key, portMAX_DELAY ); //写入队列,队列值是key地址的值
if(err == pdPASS)
{
printf("往队列queue_handle写入数据成功!!\r\n");
}
}else if(key == KEY1_PRES)
{
err = xSemaphoreGive(semphr_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 == semphr_handle)
{
xSemaphoreTake( member_handle, portMAX_DELAY ); //获取信号量
printf("获取信号量成功!!\r\n");
}
}
}
//freertos_demo.h
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H
void freertos_demo(void);
#endif