16_FreeRTOS队列集

目录

队列集

队列集相关API函数介绍

队列集使用流程

实验源码


队列集

一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集!

作用:用于对多个队列或信号量进行“监听”其中不管哪一个消息到来,都可让任务退出阻塞状态

假设:有个接收任务,使用到队列接收和信号量的获取,如下:

16_FreeRTOS队列集_第1张图片

 队列集相关API函数介绍

16_FreeRTOS队列集_第2张图片

创建队列集

QueueSetHandle_t  ( const UBaseType_t uxEventQueueLength);

此函数用于创建队列集。

16_FreeRTOS队列集_第3张图片

添加队列到队列集

BaseType_t xQueueAddToSet( 
QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet)

此函数用于往队列集中添加队列,要注意的时,队列在被添加到队列集之前,队列中不能有有效的消息

16_FreeRTOS队列集_第4张图片

从队列集中移除队列 

BaseType_t xQueueRemoveFromSet(
QueueSetMemberHandle_t 	xQueueOrSemaphore,
QueueSetHandle_t	xQueueSet);

此函数用于从队列集中移除队列)要注意的是,队列在从队列集移除之前,必须没有有效的消息 

16_FreeRTOS队列集_第5张图片

获取队列集中有有效消息的队列

QueueSetMemberHandle_t xQueueSelectFromSet(
QueueSetHandle_t  constxQueueSet, 
TickType_t xTicksToWait)

此函数用子在任务中获取队列集中有有效消息的队列

16_FreeRTOS队列集_第6张图片

队列集使用流程

 1.启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为1

2.创建队列集

3.创建队列或信号量

4.往队列集中添加队列或信号量

5.往队列发送信息或释放信号量

6.获取队列集的消息

实验源码

将设计三个任务: start_task、 task1、task2

start_task:用来创建其它任务,并创建队列集,队列/信号量,将队列/信号量添加到队列集中

Task1:用于扫描按键,当KEYO按下,往队列写入数据,当KEY1按下,释放二值信号量

task2:读取队列集中的消息,并打印

/**
  ******************************************************************************
  * @file           : user_mian.h
  * @brief          : V1.00
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include 
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
#include "queue.h"

/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*队列集句柄*/
QueueSetHandle_t queueset_handle;
/*队列句柄*/
QueueHandle_t queue_handle;
/*二值信号量句柄*/
QueueHandle_t semphr_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*/

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define TASK1_PRIO			4
//任务堆栈大小	
#define TASK1_STK_SIZE 		100  
//任务句柄
TaskHandle_t TASK1_Handler;
//任务函数
void task1(void *pvParameters);


//任务优先级
#define TASK2_PRIO			3
//任务堆栈大小	
#define TASK2_STK_SIZE 		100  
//任务句柄
TaskHandle_t TASK2_Handler;
//任务函数
void task2(void *pvParameters);


 int main(void)
 {	

	/*配置系统中断分组为4位抢占*/
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	 /*延时函数初始化*/
	 delay_init();
	/*RCC配置*/
	 Rcc_config();
	/*GPIO初始化*/ 
	 Gpio_Init();
	/*USART1初始化*/
	 Uart1_Init(9600);
	 /*创建开始任务*/
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
		

}
 

/*!
	\brief		开始任务函数
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void start_task(void *pvParameters)
{
	
    taskENTER_CRITICAL();           //进入临界区
	
	/*创建队列集,可存放2个队列*/
	queueset_handle = xQueueCreateSet(2);
	if(queueset_handle != NULL)
	{
		taskENTER_CRITICAL();           //进入临界区
		printf("队列集创建成功\r\n");
		taskEXIT_CRITICAL();            //退出临界区
	}
	
	/*创建队列*/
	 queue_handle = xQueueCreate(1,sizeof(uint8_t));
	
	/*创建二值信号量*/	
	semphr_handle = xSemaphoreCreateBinary();
	
	/*添加队列到队列集中*/
	xQueueAddToSet(queue_handle,queueset_handle);
	xQueueAddToSet(semphr_handle,queueset_handle);	
	
    //创建高优先级任务
    xTaskCreate((TaskFunction_t )task1,     	
                (const char*    )"task1",   	
                (uint16_t       )TASK1_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )TASK1_PRIO,	
                (TaskHandle_t*  )&TASK1_Handler);   
    //创建中优先级任务
    xTaskCreate((TaskFunction_t )task2,     
                (const char*    )"task2",   
                (uint16_t       )TASK2_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&TASK2_Handler); 

				
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}


/*!
	\brief		任务1实现队列发生以及信号量释放
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void task1(void *pvParameters)
{
	uint8_t 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)
			{	
				taskENTER_CRITICAL();           //进入临界区
				printf("往队列queue_handle写入数据成功**********\r\n\r\n");
				taskEXIT_CRITICAL();            //退出临界区
			}
		}else if(key == KEY1_PRES)
		{
			/*释放信号量*/
			err = xSemaphoreGive(semphr_handle);
			if(err == pdPASS)
			{	
				taskENTER_CRITICAL();           //进入临界区
				printf("释放二值信号量成功**********\r\n\r\n");
				taskEXIT_CRITICAL();            //退出临界区
			}
		}
		
		vTaskDelay(10);
    }
} 


/*!
	\brief		任务2获取队列集的消息 
	\param[in]	传递形参,创建任务时用户自己传入
	\param[out]	none
	\retval 	none
*/
void task2(void *pvParameters)
{
	QueueSetMemberHandle_t member_handle;
	uint8_t key_value;
    while(1)
    {
		/*读取队列集函数*/
		member_handle = xQueueSelectFromSet(queueset_handle,portMAX_DELAY);
		if(member_handle == queue_handle)
		{
			/*接受队列*/
			xQueueReceive(member_handle,&key_value,portMAX_DELAY);
			taskENTER_CRITICAL();           //进入临界区
			printf("队列数据是%d\r\n\r\n",key_value);
			taskEXIT_CRITICAL();            //退出临界区
		}else if(member_handle == semphr_handle)
		{
			/*获取二值信号量*/
			xSemaphoreTake(member_handle,portMAX_DELAY);
			taskENTER_CRITICAL();           //进入临界区
			printf("获取二值信号量成功\r\n\r\n");
			taskEXIT_CRITICAL();            //退出临界区
			
		}
    }
}





 /************************************************************** END OF FILE ****/

16_FreeRTOS队列集_第7张图片

你可能感兴趣的:(FreeRTOS,单片机,stm32,嵌入式硬件,FreeRTOS)