目录
队列集
队列集相关API函数介绍
队列集使用流程
实验源码
队列集
一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集!
作用:用于对多个队列或信号量进行“监听”其中不管哪一个消息到来,都可让任务退出阻塞状态。
假设:有个接收任务,使用到队列接收和信号量的获取,如下:
队列集相关API函数介绍
创建队列集
QueueSetHandle_t ( 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 constxQueueSet,
TickType_t xTicksToWait)
此函数用子在任务中获取队列集中有有效消息的队列
队列集使用流程
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 <stdbool.h>
#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 ****/