FreeRTOS入门教程(队列详细使用示例)
文章目录
- 前言
- 一、队列基本使用
- 二、如何分辨数据源
- 三、传输大块数据
- 总结
前言
上篇文章我们已经讲解了队列的概念和队列相关的API函数,那么本篇文章的话就开始带大家来学习使用队列。
一、队列基本使用
这个例子将会创建三个任务,其中两个任务用来发送数据到队列中,另一个任务用来从队列中读取数据。
void Task1Function(void * param)
{int val;while (1){val = 100;xQueueSend(xQueueCalcHandle, &val, 0);vTaskDelay(1000);}
}void Task2Function(void * param)
{int val;while (1){val = 200;xQueueSend(xQueueCalcHandle, &val, 0);vTaskDelay(1000);}
}void Task3Function(void * param)
{int val;const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );BaseType_t xStatus;while (1){xStatus = xQueueReceive(xQueueCalcHandle, &val, xTicksToWait);if( xStatus == pdPASS ){/* 读到了数据 */printf( "Received = %d\r\n", val );} else{/* 没读到数据 */printf( "Could not receive from the queue.\r\n" );} }
}xQueueCalcHandle = xQueueCreate(5, sizeof(int));xTaskCreate(Task1Function, "Task1", 100, NULL, 1, NULL);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xTaskCreate(Task3Function, "Task3", 100, NULL, 2, NULL);
运行效果:
从运行效果中可以看出,当队列中有数据的时候就能够从队列中读取到数据,当队列中没有数据时,超时后会返回pdFALSE。

这里使用百问网的一张图片来描述这个过程:

二、如何分辨数据源
通过上面这个实验我们完成了队列数据的发送和队列数据的接收,但是我们无法得知数据是哪个队列所发送的,那么下面这个实验就带大家来完成分辨数据源的实验。
前面的实验中我们使用单独的一个int变量来代表数据,这样的话只能接收到对应的数据而无法分辨是谁发过来的数据,那么有什么办法来分辨是谁发来的数据呢?
这里的解决方法是使用结构体:
typedef enum
{Task1,Task2
}ID_t;typedef struct data
{ID_t id;int data;
}Data_t;static Data_t senddata[2] = {{Task1, 10},{Task2, 20}
};void Task1Function(void * param)
{while (1){xQueueSend(xQueueCalcHandle, &senddata[0], 0);vTaskDelay(1000);}
}void Task2Function(void * param)
{while (1){xQueueSend(xQueueCalcHandle, &senddata[1], 0);vTaskDelay(1000);}
}void Task3Function(void * param)
{Data_t mydata;const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );BaseType_t xStatus;while (1){xStatus = xQueueReceive(xQueueCalcHandle, &mydata, xTicksToWait);if( xStatus == pdPASS ){/* 读到了数据 */if(mydata.id == Task1){printf("this is Task1 data :%d\r\n", mydata.data);}else{printf("this is Task2 data :%d\r\n", mydata.data);}} else{/* 没读到数据 */printf( "Could not receive from the queue.\r\n" );} }
}xQueueCalcHandle = xQueueCreate(5, sizeof(Data_t));xTaskCreate(Task1Function, "Task1", 100, NULL, 1, NULL);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xTaskCreate(Task3Function, "Task3", 100, NULL, 2, NULL);
当接收到数据时会先判断结构体中的id,通过id来判断是哪个任务发送过来的数据。
运行效果:

三、传输大块数据
FreeRTOS 中的队列通常使用数据拷贝来传递数据。这意味着当你将数据发送到队列或从队列接收数据时,队列会在内部复制数据的副本,而不是传递指向原始数据的指针。
这种数据拷贝的方法确保了数据的安全性和一致性,因为多个任务可以独立访问它们自己的副本,而不会干扰其他任务。然而,需要注意的是,数据拷贝可能会引入一些性能开销,尤其是在处理大量数据时。
那么当使用队列来传输大量数据时该怎么做呢?
这里我们可以使用指针来解决这个问题,传递大块数据的时候我们可以使用指针来解决这个问题,在传输大块数据时,可以先得到数据的地址,将数据的地址作为数据传递过来,当接收到数据的地址时,就能够通过数据的地址来得到对应的数据了。
示例:
char pcbuffer[100] = "Hello World";void Task1Function(void * param)
{char* buffer;while (1){buffer = pcbuffer;xQueueSend(xQueueCalcHandle, &buffer, 0);vTaskDelay(1000);}
}void Task2Function(void * param)
{char* buffer;while (1){buffer = pcbuffer;xQueueSend(xQueueCalcHandle, &buffer, 0);vTaskDelay(1000);}
}void Task3Function(void * param)
{char* rebuffer;const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );BaseType_t xStatus;while (1){xStatus = xQueueReceive(xQueueCalcHandle, &rebuffer, xTicksToWait);if( xStatus == pdPASS ){/* 读到了数据 */printf("recv buffer : %s\r\n", rebuffer);} else{/* 没读到数据 */printf( "Could not receive from the queue.\r\n" );} }
}xQueueCalcHandle = xQueueCreate(5, sizeof(char*));
if (xQueueCalcHandle == NULL)
{printf("can not create queue\r\n");
}xTaskCreate(Task1Function, "Task1", 100, NULL, 1, NULL);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xTaskCreate(Task3Function, "Task3", 100, NULL, 2, NULL);
运行结果:

这里有几个点需要注意:
1.
由于队列传递数据是复制数据的副本,所有传输数据时并不会影响到原来的数据,但是在这里使用到了地址,当改变这个地址空间的数据后,原来的数据也会受到影响。
2.
由于传递的是地址空间,那么这里的话就必须保证这个数据是全局数据,因为局部数据会被释放,释放后就无法进行使用了,所有需要保证数据是全局数据。
总结
本篇文章就讲解到这里,本篇文章主要给大家讲解了队列的具体代码和使用方法。
相关文章:
FreeRTOS入门教程(队列详细使用示例)
文章目录 前言一、队列基本使用二、如何分辨数据源三、传输大块数据总结 前言 上篇文章我们已经讲解了队列的概念和队列相关的API函数,那么本篇文章的话就开始带大家来学习使用队列。 一、队列基本使用 这个例子将会创建三个任务,其中两个任务用来发送…...
【Kafka专题】Kafka收发消息核心参数详解
目录 前置知识课程内容一、从基础的客户端说起(Java代码集成使用)1.1 消息发送者源码示例1.2 消息消费者源码示例1.3 客户端使用小总结 *二、从客户端属性来梳理客户端工作机制*2.1 消费者分组消费机制2.2 生产者拦截器机制2.3 消息序列化机制2.4 消息分…...
matlab 使用激光雷达检测、分类和跟踪车辆
目录 1、算法概述2、加载数据3、地平面分割4、语义分割5、聚类和边界盒拟合6、可视化设置7、循环遍历数据8、面向跟踪的包围盒9、 总结10、 支持功能11、 参考</...
代码随想录训练营二刷第四十八天 | 139.单词拆分 背包问题总结
代码随想录训练营二刷第四十八天 | 139.单词拆分 背包问题总结 一、139.单词拆分 题目链接:https://leetcode.cn/problems/word-break/ 思路:单词拼字符串,完全背包。定义dp[i],为true表示可以拆分为一或多个单词。可能会出现ab…...
【数据挖掘】2017年 Quiz 1-3 整理 带答案
目录 Quiz 1Quiz 2Quiz 3Quiz 1 Answer Problems 1-2 based on the following training set, where A , B , C A, B, C A,B,</...
吃鸡高手必备工具大揭秘!提高战斗力,分享干货,一站满足!
大家好!你是否想提高吃鸡游戏的战斗力,分享顶级的游戏作战干货,方便进行吃鸡作图和查询装备皮肤库存?是否也担心被骗,希望查询游戏账号是否在黑名单上,或者查询失信人和VAC封禁情况?在这段视频中…...
集群化环境前置准备
目录 部署 1. 配置多台Linux虚拟机 1.1 首先,关机当前CentOS系统虚拟机(可以使用root用户执行init 0来快速关 机) 1.2 新建文件夹 1.3 克隆 1.4 同样的操作克隆出:node2和node3 1.5 开启node1,修改主机名为node1&…...
nodejs开发环境搭建
Nodejs是一个开源的、跨平台JavaScript运行时环境,其使用V8引擎对JavaScript脚本执行解释,在前后端分离的应用架构设计中,其既能支持web页面服务应用的开发、也能支持后端接口服务应用的开发,类似于Java语言的J2EE运行时环境&…...
C语言qsort函数
排序qsort int int cmp(const void *a, const void *b) {return *(int *)a - *(int *)b;//先强转成int型,后解引用取值比较大小 }字符串数组 char a[] “hello world” //字符串数组,存放的是字符 int cmp(const void *a, const void *b) {return *(…...
如何使用 Hotshot 通过文字生成 GIF 动画
Hotshot 是一个基于人工智能的工具,可用于通过文字生成 GIF 动画。该工具使用最新的图像生成技术来创建逼真的动画,即使是复杂的文字描述也能做到。 hotshot访问地址 使用 Hotshot 生成 GIF 动画 要使用 Hotshot 生成 GIF 动画,您需要首先…...
吃鸡高手必备!这些技巧帮你提高战斗力!
大家好!作为一名吃鸡玩家,我们都想提高自己的战斗力,享受顶级游戏作战干货,装备皮肤库存展示和查询,并避免被骗游戏账号。在这里,我将为大家介绍一些实用的技巧和工具,让你成为吃鸡高手…...
XV6 操作系统实验
环境搭建 ubuntu 新建一个文件setup.sh,内容如下 #获取工具链 git clone --recursive https://github.com/riscv/riscv-gnu-toolchain #安装必要依赖 sudo apt-get update sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev li…...
leetcode - 双周赛114
一,2869.收集元素的最小操作次数 // 解法:哈希表 从右往左遍历 class Solution {public int minOperations(List<Integer> nums, int k) {Set<Integer> set new HashSet<>();for(int i1; i<k; i){set.add(i);}for(int inums.size…...
【LeetCode刷题笔记】双指针
剑指 Offer 21.调整数组顺序使奇数位于偶数前面 解题思路: 对撞指针 , 从左边不停的找第一个偶数,从右边不停的找第一个奇数 ,找到后 交换 两者位置 本题与【905. 按奇偶排序数组】几乎雷同。 剑指 Offer 57.和为s的两个数字 本题…...
互联网Java工程师面试题·Memcached 篇·第二弹
目录 10、memcached 如何实现冗余机制? 11、memcached 如何处理容错的? 12、如何将 memcached 中 item 批量导入导出? 13、如果缓存数据在导出导入之间过期了,您又怎么处理这些数据呢? 14、memcached 是如何做身份…...
特斯拉被称为自动驾驶领域的苹果
特斯拉的自动驾驶技术无疑是居于世界上领先地位的,有人形容特斯拉是自动驾驶汽车领域的苹果。特斯拉发布的Tesla Vision系统只配备了摄像头,不依靠雷达。 这并不是特斯拉唯一和其它对手不同的地方,他们的整个战略都是基于车队和销售产品,而其大多数竞争对手则销售自…...
stm32之HAL库操作PAJ75620
一、模块简介 手势模块PAJ7620主要利用IIC或SPI协议来实现数据的传输,本实验用的模块是以IIC来进行信息传输。支持电压从2.8v到3.6v, 正常可以选择3.3v。检测的距离从5到15cm, 可以检测9种手势,包括 右:编码为 0x01左:编码为 0x0…...
医学影像归档与通讯系统(PACS)系统源码 PACS三维图像后处理技术
医学影像归档与通讯系统(PACS)系统源码 PACS三维图像处理 医学影像归档与通讯系统(PACS)系统,是一套适用于从单一影像设备到放射科室、到全院级别等各种应用规模的医学影像归档与通讯系统。PACS集患者登记、图像采集、…...
web漏洞-PHP反序列化
目录 PHP反序列化序列化反序列化原理涉及技术利用危害CTF靶场 PHP反序列化 序列化 将对象转换成字符串 反序列化 相反,将字符串转换成对象。 数据格式的转换对象的序列化有利于对象的保存和传输,也可以让多个文件共享对象。 原理 未对用户输入的序列化字…...
Redis-分布式锁
分布式锁相关内容 超卖问题切入可以使用互斥锁给先获取到锁的线程加锁吗?使用redis分布式锁解决超卖问题setnx命令实现分布式锁为什么需要设置过期时间?Redis实现分布式锁如何合理控制锁的有效时长 redisson实现分布式锁 超卖问题切入 我们先来看一个项目…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
