freeRTOS总结(十二)队列集

1,队列集简介(了解)

一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集 !
作用:用于对多个队列或信号量进行“监听”,其中不管哪一个消息到来,都可让任务退出阻塞状态
假设:有个接收任务,使用到队列接收和信号量的获取,如下:
在这里插入图片描述
如果此时释放了信号量该任务本能获取信号量,但是如果接收队列时该队列中没有值,当前该任务会被放入阻塞状态。那本应获取到的信号量也获取不到。

2,队列集相关API函数介绍(熟悉)

在这里插入图片描述
用于创建队列集

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 )

此函数用于在任务中获取队列集中有有效消息的队列
在这里插入图片描述
在这里插入图片描述

3,队列集操作实验(掌握)

1、实验目的:学习 FreeRTOS 的队列集相关API的使用。
2、实验设计:将设计三个任务:start_task、task1、task2
三个任务的功能如下:
start_task:用来创建其它任务,并创建队列集,队列/信号量,将队列/信号量添加到队列集中
task1:用于扫描按键,当KEY0按下,往队列写入数据,当KEY1按下,释放二值信号量
task2:读取队列集中的消息,并打印

队列集使用流程
1、启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为 1
2、创建队列集
3、创建队列或信号量
4、往队列集中添加队列或信号量
5、往队列发送信息或释放信号量
6、获取队列集的消息


#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 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 
#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;
void task1( void * pvParameters );


/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO         3
#define TASK2_STACK_SIZE   128
TaskHandle_t   task2_handler;
void task2( void * pvParameters );


#define QUEUE_NUM 2
/******************************************************************************************************/
QueueSetHandle_t g_queueset_handle;/*声明队列集*/
QueueHandle_t g_queue_handle; /*声明队列*/
QueueHandle_t g_bin_semphore_handle;/*声明二值信号量*/

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
	void freertos_demo(void)
{ 
BaseType_t err;

/*********************************创建队列集*********************************************************************/
g_queueset_handle= xQueueCreateSet(QUEUE_NUM);/* 创建队列集 */

if(g_queueset_handle!=NULL)
{
	printf("创建队列集成功!!!!\r\n");

}
else
{
	printf("创建队列集失败!!!!\r\n");
}
g_queue_handle=xQueueCreate(1,sizeof(uint8_t)); /* 创建队列*/
if(g_queue_handle!=NULL)
{
	printf("创建队列成功!!!!\r\n");

}
else
{
	printf("创建队列失败!!!!\r\n");
}
g_bin_semphore_handle=xSemaphoreCreateBinary(); /* 创建二值信号量 */
if(g_bin_semphore_handle!=NULL)
{
	printf("创建二值信号量成功!!!!\r\n");

}
else
{
	printf("创建二值信号量失败请检查错误!!!!\r\n");

}
err=xQueueAddToSet( g_queue_handle,g_queueset_handle);
if(err==pdTRUE)
{
	printf("队列添加到队列集成功!\r\n");
}
else
{
	printf("队列添加到队列集失败!\r\n");
}
err=xQueueAddToSet( g_bin_semphore_handle,g_queueset_handle);
if(err==pdTRUE)
{
	printf("信号量添加到队列集成功!\r\n");
}
else
{
	printf("信号量添加到队列集失败!\r\n");
}
	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();               /* 进入临界区  任何任务和中断都不能打断当前程序运行*/
		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();
							
	

}
/* 任务一,用于扫描按键,当KEY0按下,往队列写入数据,当KEY1按下,释放二值信号量 */
void task1( void * pvParameters )
{
		BaseType_t err;
		uint8_t key;
		while(1)
		{
			key=key_scan(0);
			if(key==KEY0_PRES)
			{
				/*往队列写入数据*/
				err=xQueueSend(g_queue_handle,&key,portMAX_DELAY);
				if(err==pdPASS)
				{
					printf("往队列写入queue_handle写入数据成功");
				}
			}
			else if(key==KEY1_PRES)
			{
				/*释放二值信号量*/
				err = xSemaphoreGive(g_bin_semphore_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( g_queueset_handle,portMAX_DELAY);
		if(member_handle==g_queue_handle)
		{
			xQueueReceive(member_handle,&key,portMAX_DELAY);
			printf("获取到的数据队列为:%d\r\n",key);
		}
		else if(member_handle==g_bin_semphore_handle)
		{
			xSemaphoreTake(member_handle,portMAX_DELAY);
			 printf("获取信号量成功!!\r\n");
		}
	}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值