FreeRTOS从入门到精通 第十四章(队列集)

参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili

一、队列集简介

1、队列集概述

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

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

(3)队列集大致使用流程:

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

②创建队列集。

③创建队列或信号量。

④往队列集中添加队列或信号量。

⑤往队列发送信息或释放信号量。

⑥获取队列集的消息。

2、队列集相关API函数介绍

(1)队列集相关API函数概览:

函数

描述

xQueueCreateSet()

创建队列集

xQueueAddToSet()

队列添加到队列集中【队列在被添加到队列集之前,队列中不能有有效的消息】

xQueueRemoveFromSet()

从队列集中移除队列【队列在从队列集移除之前,必须没有有效的消息】

xQueueSelectFromSet()

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

xQueueSelectFromSetFromISR()

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

(2)xQueueCreateSet函数:

①函数定义:

QueueSetHandle_t xQueueCreateSet
(
    const  UBaseType_t   uxEventQueueLength
); 

②函数参数:

形参

描述

uxEventQueueLength 

队列集可容纳的队列数量

③返回值:

返回值

描述

NULL 

队列集创建失败

其它值 

队列集创建成功,返回队列集句柄

(3)xQueueAddToSet函数:

①函数定义:

BaseType_t xQueueAddToSet
(
    QueueSetMemberHandle_t   	xQueueOrSemaphore ,
    QueueSetHandle_t   		    xQueueSet
); 

②函数参数:

形参

描述

xQueueOrSemaphore 

待添加的队列句柄

xQueueSet 

队列集

③返回值:

返回值

描述

pdPASS 

队列集添加队列成功

pdFAIL 

队列集添加队列失败

(4)xQueueRemoveFromSet函数:

①函数定义:

BaseType_t xQueueRemoveFromSet
(
    QueueSetMemberHandle_t  	xQueueOrSemaphore ,
	QueueSetHandle_t   		xQueueSet
); 

②函数参数:

形参

描述

xQueueOrSemaphore 

待移除的队列句柄

xQueueSet 

队列集

③返回值:

返回值

描述

pdPASS 

队列集添加队列成功

pdFAIL 

队列集添加队列失败

(5)xQueueSelectFromSet函数:

①函数定义:

QueueSetMemberHandle_t xQueueSelectFromSet
(
    QueueSetHandle_t 	xQueueSet,
    TickType_t const 		xTicksToWait
)

②函数参数:

形参

描述

xQueueSet 

队列集

xTicksToWait 

阻塞超时时间

③返回值:

返回值

描述

NULL 

获取消息失败

其他值 

获取到消息的队列句柄

二、队列集操作实验

1、原理图与实验目标

(1)原理图(串口外设的接法与列表项的插入和删除实验相同,下图未示出):

(2)实验目标:

①设计3个任务——start_task、task1、task2:

[1]start_task:用于创建其它任务,并创建队列集,队列/信号量,将队列/信号量添加到队列集中。

[2]task1:用于扫描按键,当按键1按下,往队列写入数据,当按键2按下,释放二值信号量。

[3]task2:读取队列集中的消息,并打印。

②预期实验现象:

[1]程序下载到板子上后,板子上无任何明显现象。

[2]串口助手中输出相关调试信息。

2、实验步骤

(1)将“列表项的插入和删除实验”的工程文件夹复制一份,在拷贝版中进行实验。

(2)在FreeRTOSConfig.h文件中将宏configUSE_QUEUE_SETS配置为1。

#define configUSE_QUEUE_SETS    1

(3)更改FreeRTOS_experiment.c文件的内容,如下所示。

#include "FreeRTOS.h"
#include "task.h"
#include "LED.h"
#include "Key.h"
#include "Serial.h"
#include "queue.h"
#include "semphr.h"

//宏定义
#define START_TASK_STACK_SIZE 128   //start_task任务的堆栈大小
#define START_TASK_PRIO        1     //start_task任务的优先级
#define TASK1_STACK_SIZE       128   //task1任务的堆栈大小
#define TASK1_PRIO              2     //task1任务的优先级
#define TASK2_STACK_SIZE       128   //task2任务的堆栈大小
#define TASK2_PRIO              3     //task2任务的优先级

//任务函数声明
void start_task(void);
void task1(void);
void task2(void);

//任务句柄
TaskHandle_t start_task_handler;     //start_task任务的句柄
TaskHandle_t task1_handler;         //task1任务的句柄
TaskHandle_t task2_handler;         //task2任务的句柄

QueueSetHandle_t queueset_handle;
QueueHandle_t    queue_handle;
QueueHandle_t    semphr_handle;

void FreeRTOS_Test(void)
{
	//创建任务start_task
	xTaskCreate((TaskFunction_t)start_task,            //指向任务函数的指针
				"start_task",                       //任务名字
				START_TASK_STACK_SIZE,       //任务堆栈大小,单位为字
				NULL,                          //传递给任务函数的参数
				START_TASK_PRIO,              //任务优先级
				(TaskHandle_t *) &start_task_handler  //任务句柄,就是任务的任务控制块
				);
	
	//开启任务调度器
	vTaskStartScheduler();
}

void start_task(void)
{
	taskENTER_CRITICAL();                        //进入临界区
    queueset_handle = xQueueCreateSet(2);             //创建队列集,可以存放2个队列
    if(queueset_handle != NULL)
    {
        Serial_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)
{
    uint8_t key = 0;
    BaseType_t err = 0;
    while(1) 
    {
        key = Key_GetNum();
        if(key == 1)
        {
            err = xQueueSend(queue_handle, &key, portMAX_DELAY );
            if(err == pdPASS)
            {
                Serial_Printf("往队列queue_handle写入数据成功!!\r\n");
            }
        }
        else if(key == 2)
        {
            err = xSemaphoreGive(semphr_handle);
            if(err == pdPASS)
            {
                Serial_Printf("释放信号量成功!!\r\n");
            }
        }
        vTaskDelay(10);
    }
}

void task2(void)
{
    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);
            Serial_Printf("获取到的队列数据为:%d\r\n",key);
        }
        else if(member_handle == semphr_handle)
        {
            xSemaphoreTake(member_handle, portMAX_DELAY);
            Serial_Printf("获取信号量成功!!\r\n");
        }
    }
}

(4)程序完善好后点击“编译”,然后将程序下载到开发板上,打开串口助手分析信息。

3、程序执行流程

(1)main函数全流程:

①初始化串口模块。

②调用FreeRTOS_Test函数。

(2)测试函数全流程:

①创建任务start_task。

②开启任务调度器。

(3)多任务调度执行阶段较为简单,这里不再赘述。

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

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

相关文章

Python Matplotlib库:从入门到精通

Python Matplotlib库:从入门到精通 在数据分析和科学计算领域,可视化是一项至关重要的技能。Matplotlib作为Python中最流行的绘图库之一,为我们提供了强大的绘图功能。本文将带你从Matplotlib的基础开始,逐步掌握其高级用法&…

xclode版本

直接搜xcode https://developer.apple.com/download/all/?qCommand%20Line%20Tools https://developer.apple.com/download/all/?qXcode https://xcodereleases.com/?q10.15 下载可能慢 catalina 支持 11.3.1xcode

Formality:时序变换(二)(不可读寄存器移除)

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一、引言 时序变换在Design Compiler的首次综合和增量综合中都可能发生,它们包括:时钟门控(Clock Gating)、寄存器合并(Register Merging)、…

AI作画提示词:Prompts工程技巧与最佳实践

成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于物联网智能项目之——智能家居项目…

Python动量策略实战:大幅跑赢市场的底层逻辑

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话:最近我深入研究了一种基于动量策略的量化投资方法,并用Python实现了它。动量策略的核心是“追涨杀跌”,通过历史数据预测未来趋势。在这篇文章中&#…

【Proteus仿真】【51单片机】多功能计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、加减乘除,开方运算 4、带符号运算 5、最大 999*999 二、使用步骤 基于51单片机多功能计算器 包含:程序&…

链表的介绍

目录 引言优缺点与链表相似的数据结构注意事项单向链表的实现基础实现创建类创建成员变量创建特殊方法 增加数据push_back方法insert方法 删除数据del_back方法del_index方法 clear方法查询数据at方法与重载的中括号运算符toArray方法indexOf方法 修改数据获取链表大小测试方法…

【AIGC学习笔记】扣子平台——精选有趣应用,探索无限可能

背景介绍: 由于近期业务发展的需求,我开始接触并深入了解了扣子平台的相关知识,并且通过官方教程自学了简易PE工作流搭建的技巧。恰逢周会需要准备与工作相关的分享主题,而我作为一个扣子平台的初学者,也想探索一下这…

DeepSeek-R1部署教程(基于Ollama)

虽说在过年,但不能忘了学习。这几天科技圈最火的莫过于deepseek,我抽空也学习一下deepseek的部署过程。 1、下载Ollama并安装 https://github.com/ollama/ollama/releases/latest/download/OllamaSetup.exe 下载好后双击直接运行。 2、安装deepseek …

jenkins-k8s pod方式动态生成slave节点

一. 简述: 使用 Jenkins 和 Kubernetes (k8s) 动态生成 Slave 节点是一种高效且灵活的方式来管理 CI/CD 流水线。通过这种方式,Jenkins 可以根据需要在 Kubernetes 集群中创建和销毁 Pod 来执行任务,从而充分利用集群资源并实现更好的隔离性…

力扣面试150 快乐数 循环链表找环 链表抽象 哈希

Problem: 202. 快乐数 👩‍🏫 参考题解 Code public class Solution {public int squareSum(int n) {int sum 0;while(n > 0){int digit n % 10;sum digit * digit;n / 10;}return sum;}public boolean isHappy(int n) {int slow n, fast squa…

【C++】设计模式详解:单例模式

文章目录 Ⅰ. 设计一个类,不允许被拷贝Ⅱ. 请设计一个类,只能在堆上创建对象Ⅲ. 请设计一个类,只能在栈上创建对象Ⅳ. 请设计一个类,不能被继承Ⅴ. 请设计一个类,只能创建一个对象(单例模式)&am…

LLM 推理

https://www.bilibili.com/video/BV16yqeYhELh/ 大模型推理加速目标:高吞吐、低延迟 TGI vLLM SGLang LMDeploy 商汤 和 上海人工智能实验室 一起开发 缺点 性能对比 分析总结 https://www.bilibili.com/video/BV16yqeYhELh/ 大模型推理加速目标:高吞吐…

UE(UltraEdit) 配置简易C/C++编译运行环境

该类型其他帖子 EmEditor 配置简易C/C 编译运行环境_emeditor 代码运行-CSDN博客 RJ TextEd 配置简易C/C 编译运行环境-CSDN博客 这种配置适合ACM竞赛,即要求不使用现代IDE,又想用一个比较好用、至少支持代码高亮的编辑器。 前提条件 1.Mingw GCC 已…

XSS 漏洞全面解析:原理、危害与防范

目录 前言​编辑 漏洞原理 XSS 漏洞的危害 检测 XSS 漏洞的方法 防范 XSS 漏洞的措施 前言 在网络安全的复杂版图中,XSS 漏洞,即跨站脚本攻击(Cross - Site Scripting),是一类极为普遍且威胁巨大的安全隐患。随着互…

Alfresco Content Services dockerCompose自动化部署详尽操作

Alfresco Content Services docker社区部署文档 Alfresco Content Services简介 Alfresco Content Services(简称ACS)是一款功能完备的企业内容管理(ECM)解决方案,主要面向那些对企业级内容管理有高要求的组织。具体…

LCR 139.训练计划 I

目录 题目过程解法双指针法(两端开始)快慢指针 题目 教练使用整数数组 actions 记录一系列核心肌群训练项目编号。为增强训练趣味性,需要将所有奇数编号训练项目调整至偶数编号训练项目之前。请将调整后的训练项目编号以 数组 形式返回。 过…

AboutDialog组件的功能和用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了AlertDialog Widget相关的内容,本章回中将介绍AboutDialog Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的AboutDialog是一种弹出式窗口,和上一章回中介绍的Al…

Redis学习之哨兵二

一、API 1.sentinel masters:展示被监控的主节点状态及相关的统计信息 2.sentinel master <master name>:展示指定的主节点的状态以及相关的统计信息 3.sentinel slaves <master name>:展示指定主节点的从节点状态以及相关的统计信息 4.sentinel sentinels <mas…

03链表+栈+队列(D2_栈)

目录 讲解一&#xff1a;栈 一、基本介绍 二、代码示例 ------------------------------ 讲解二&#xff1a;单调栈 一、基本介绍 二、适用场景 三、情形示例 1. 寻找左边第一个小于它的数 2. 寻找左边第一个小于它的数的下标 3. 寻找右边第一个大于它的数 4. 寻找右…