15.队列集

1.简介

在使用队列进行任务之间的“沟通交流”时,一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集。FreeRTOS提供的队列集功能可以对多个队列进行“监听”,只要被监听的队列中有一个队列有有效的消息,那么队列集的读取任务都可以读取到消息,如果读取任务因读取队列集而被阻塞,那么队列集将解除读取任务的阻塞。使用队列集的好处在于,队列集可以是的任务可以读取多个队列中的消息,而无需遍历所有待读取的队列,以确定具体读取哪一个队列。

使用队列集功能,需要在 FreeRTOSConfig.h 文件中将配置项 configUSE_QUEUE_SETS 配
置为 1,来启用队列集功能。
在这里插入图片描述

2.相关API函数

在这里插入图片描述

1. 函数 xQueueCreateSet()

此函数用于创建队列集,该函数在 queue.c 文件中有定义,函数的原型如下所示:

QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength);

在这里插入图片描述

QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
{
 QueueSetHandle_t pxQueue;
 
 /* 创建一个队列作为队列集
 * 队列长度为队列集可容纳的队列数量
 * 队列项目的大小为队列控制块的大小
 * 队列的类型为队列集
 */
 pxQueue = xQueueGenericCreate( uxEventQueueLength,
 ( UBaseType_t ) sizeof( Queue_t * ),
 queueQUEUE_TYPE_SET );
 
 return pxQueue;
}

2. 函数 xQueueAddToSet()

此函数用于往队列集中添加队列,要注意的时,队列在被添加到队列集之前,队列中不能
有有效的消息,该函数在 queue.c 文件中有定义,函数的原型如下所示:

BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
 QueueSetHandle_t xQueueSet);

在这里插入图片描述
函数 xQueueAddToSet()的具体代码如下所示:

BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet)
{
 BaseType_t xReturn;
 
 /* 进入临界区 */
 taskENTER_CRITICAL();
 {
 if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
 {
 xReturn = pdFAIL;
 }
 /* 队列中要求没有有效消息 */
 else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting !=
 ( UBaseType_t ) 0 )
 {
 xReturn = pdFAIL;
 }
 else
 {
 /* 将队列所在队列集设为队列集 */
 ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer =
 xQueueSet;
 xReturn = pdPASS;
 }
 }
 /* 退出临界区 */
 taskEXIT_CRITICAL();
 
 return xReturn;
}

3. 函数 xQueueRemoveFromSet()

此函数用于从队列集中移除队列,要注意的时,队列在从队列集移除之前,必须没有有效
的消息,该函数在 queue.c 文件中有定义,函数的原型如下所示:

BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,
 QueueSetHandle_t xQueueSet);

在这里插入图片描述
在这里插入图片描述
函数 xQueueRemoveFromSet()的具体代码如下所示:

BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,
 QueueSetHandle_t xQueueSet)
{
 BaseType_t xReturn;
 Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;
 
 /* 队列需在队列集中,才能移除 */
 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
 {
 xReturn = pdFAIL;
 }
 /* 队列中没有有效消息时,才能移除 */
 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )
 {
 xReturn = pdFAIL;
 }
 else
 {
 /* 进入临界区 */
 taskENTER_CRITICAL();
 {
 /* 将队列所在队列集设为空 */
 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
 }
 /* 退出临界区 */
 taskEXIT_CRITICAL();
 xReturn = pdPASS;
 }
 
 return xReturn;
}

4. 函数 xQueueSelectFromSet()

此函数用于在任务中获取队列集中有有效消息的队列,该函数在 queue.c 文件中有定义,函
数的原型如下所示:

QueueSetMemberHandle_t xQueueSelectFromSet(
 QueueSetHandle_t xQueueSet,
 TickType_t const xTicksToWait);

在这里插入图片描述
在这里插入图片描述
函数 xQueueSelectFromSet()的具体代码如下所示:

QueueSetMemberHandle_t xQueueSelectFromSet(
 QueueSetHandle_t xQueueSet,
 TickType_t const xTicksToWait)
{
 QueueSetMemberHandle_t xReturn = NULL;
 
 /* 读取队列集的消息
 * 读取到的消息,
 * 即为队列集中有空闲消息的队列
 */
 ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet,
 &xReturn,
 xTicksToWait);
 return xReturn;
}

5. 函数 xQueueSelectFromSetFromISR()

此函数用于在中断中获取队列集中有有效消息的队列,该函数在 queue.c 文件中有定义,函
数的原型如下所示:

QueueSetMemberHandle_t xQueueSelectFromSetFromISR(
 QueueSetHandle_t xQueueSet );

在这里插入图片描述

QueueSetMemberHandle_t xQueueSelectFromSetFromISR(
 QueueSetHandle_t xQueueSet )
{
 QueueSetMemberHandle_t xReturn = NULL;
 /* 在中断中读取队列集的消息
 * 读取到的消息,
 * 即为队列集中有空闲消息的队列
 */
 ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet,
 &xReturn,
 NULL);
 return xReturn;
}

3.相关实验

在这里插入图片描述

#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);
        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(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");
        }
    }
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/526687.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构与算法】—— 二叉树

目录 一、树 1、初识树 2、树的一些概念 3、树的表示形式 二、二叉树 1、初识二叉树 2、两种特殊的二叉树 3、二叉树的性质 4、二叉树的遍历 5、实现一棵二叉树 6、二叉树题目(没代码的后面会给补上) 一、树 1、初识树 (1&…

从人机界面设计黄金三法则视角看 ChatGPT 的界面设计的“好”与“坏”

热门文章推荐: (1)《为什么很多人工作 3 年 却只有 1 年经验?》(2)《一文掌握大模型提示词技巧:从战略到战术巧》(3)《AI 时代,程序员的出路在何方&#xff1…

破晓数据新纪元:隐语隐私计算,携手共创安全智能的未来生态

1.业务背景:安全核对产生的土壤 隐语隐私计算在安全核对业务背景下的应用,主要聚焦于解决企业在数据交换和分析过程中面临的隐私保护问题。 在许多行业中,特别是在金融、医疗、政务等领域,数据的安全核对至关重要,例如…

三流大学毕业,物流专业转行自述:“从月薪4K到现在月入2W+,我做到了哪些?”

我是25岁转行学python的。说实在,转行就是奔着挣钱去的。希望我的经历可以给想转行的朋友带来一点启发和借鉴。 先简单介绍下个人背景,三流大学毕业,物流专业,学习能力一般,没啥特别技能,反正就很普通的一…

《springcloud alibaba》 四 seata安装以及使用

目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlappli…

python代码使用过程中使用快捷键注释时报错

1.代码 2.代码报错 3.代码注释后的结果 4. 原因

动态输出n位小数——满满都是坑!

【题目描述】 输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b ≤10^6 ,c≤100。输入包含多组数据,结束标记为a=b=c=0。 【样例输入】 1 6 4 0 0 0 【样…

HIDS是什么,如何保护主机系统

随着网络安全攻防对抗的日趋激烈,主机当前企业和组织的安全运营工作面临的挑战越来越突出,外网防护的同时,内网主机安全防护也越来越重要。 HIDS(Host-based Intrusion Detection System),是基于主机型入侵检测系统的简称。作为计…

30万奖金谁能瓜分?OurBMC开源大赛决赛入围名单公示

首届开放原子开源大赛基础软件赛道自今年 1 月开启报名以来,吸引了全国各地 BMC 技术爱好者的广泛关注和踊跃报名。该赛事由开放原子开源基金会牵头, OurBMC 社区及理事长单位飞腾信息技术有限公司联合承办,以 “基于 BMC 技术的服务器故障诊…

抖音电商罗盘品牌人群运营策略指南

【干货资料持续更新,以防走丢】 抖音电商罗盘品牌人群运营策略指南 部分资料预览 资料部分是网络整理,仅供学习参考。 抖音运营资料合集(完整资料包含以下内容) 目录 品牌人群运营策略,旨在帮助品牌通过精细化运营提…

雅虎套餐发稿独家技巧,让你的媒体宣发效率翻倍

在如今的信息时代,媒体宣发是每个品牌和公司都不可或缺的一部分。而雅虎套餐发稿,作为其中的一种方式,更是受到了许多人的青睐。那么,如何才能充分利用雅虎套餐发稿的功能,让你的媒体宣发效率翻倍呢?以下就…

Java 解决 Process 执行命令行命令报【CreateProcess error=2, 系统找不到指定的文件。】错误问题

目录 问题 问题代码 解决方案 判断操作系统 问题 使用 Process 执行命令行命令时,报 CreateProcess error2, 系统找不到指定的文件。但明明指定的文件是存在的。而且这种错误只在 IDEA 中运行会报错,打包后直接 java -jar 运行就能正常运行&#xf…

【绩效管理】帮助零售企业建立分层分类绩效考核体系项目纪实

购物中心张经理评价:“员工的绩效管理一直是困扰我公司的难题,我们只懂得怎么经营,至于怎么做人力资源管理,真是一点都不懂。这次华恒智信为我们提供的服务对我们的帮助很大。基于企业实际调研情况,华恒智信专家明确指…

高维解码|Redis 收紧许可证!开源软件公司如何在云时代生存?

最近,Redis 从开放源代码的 BSD 许可证过渡到了更加限制性的 Server Side Public License (SSPLv1)。一石激起千层浪,Redis 的这一举动,不仅分化了前 Redis 维护者,也再次引发业界对于“开源项目可持续性以及许可证决策对其社区的…

easyExcel - 按模板导出

目录 前言一、情景介绍二、文档介绍2.1 读取模板2.2 填充模板 三、代码示例3.1 案例一:工资表3.2 案例二:报价单 四、我所遇到的问题 前言 Java-easyExcel入门教程:https://blog.csdn.net/xhmico/article/details/134714025 之前有介绍过如…

无尽加班何时休--状态模式

1.1 加班,又是加班! 公司的项目很急,所以要求加班。经理把每个人每天的工作都排得满满的,说做完就可以回家,但是没有任何一个人可以在下班前完成的,基本都得加班,这就等于是自愿加班。我走时还有…

查看Linux系统相关信息

注: 本文只是博主学习记录分享,仅供参考。如有错误肯定是博主理解有问题,谢谢! 一、查看当前操作系统的内核信息 命令:uname -a 二、查看当前操作系统版本信息 命令:cat /proc/version 这条命令可以查看到…

Your file appears not to be a valid OLE2 document

前言 org.apache.poi.poifs.filesystem.NotOLE2FileException:Invalid header signature; read 0x0000000000000000, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document解决 Excel兼容模式打开老版本文件造成文件损坏,大多说的是点…

OPC UA遇见chatGPT

最近opc 基金会将召开一个会议,主题是”OPC UA meets IT“。由此可见,工业自动化行业也开始研究和评估chatGPT带来的影响了。 本文谈谈本人对OPC UA 与chatGPT结合的初步实验和思考。 构建OPC UA 信息模型 chatGPT 的确非常强大了,使用自然…

Redis 主从复制、哨兵模式、Cluster集群

目录 一、Redis 主从复制 1、主从复制介绍 2、主从复制的作用 3、主从复制流程: 4、搭建redis主从复制 4.1所有服务器搭建redis数据库 4.2修改Redis配置文件(Master节点操作) ​4.3修改Redis配置文件(slave节点操作&#x…