(ESP32学习7)双核使用队列进行任务间通信

2023-10-27

这里是调用双核的方法哈,和我们单核使用的方法不兼容,因为有一些函数是不一样的,不通用,但是下一篇博文我会更一篇单核使用队列进行任务间通讯的问题

队列是什么?

队列是可以从一个任务向其他任务以并发安全的方式发送消息的机制,也就是说他的目标是实现任务间的通讯,比如A任务向名为Queue的队列中发布了数据,那么B任务就可以从Queue这个队列中又把数据给取出来,并且,这个数据是复制式的,也就是说把数据复制一份送入队列,B任务取出后对原来A的数据完全不会造成影响(实际上是形象的描述,本质上是通过一系列指针实现的),好了知道一些概念就行了,重要的是知道怎么用

先上代码,然后里面的注释我都注释的非常清楚了,然后再给大家说说一些需要注意的点以及我查资料写这一段代码的一点思考,代码有一点点长但是不要被吓到,其实核心并不多
#include <soc/soc.h> 
#include <soc/rtc_cntl_reg.h>
#include <stdio.h>
#include <stdlib.h>

//这是队列数据结构体,数据是可以以结构体存在的
typedef struct{
  int sender;
  char *msg;
}Data;

//以下句柄名字以x开头,用作双核版本的队列测试
xQueueHandle xqueue0;  //创建的测试队列句柄,我们定义数据为int型
xQueueHandle xqueue1;  //创建的测试队列句柄,我们定义数据为字符串型
xQueueHandle xqueue2;  //创建的测试队列句柄,我们定义数据为结构体型,结构体里面包括一个int型以及一个字符串型
TaskHandle_t xTask0;   //任务0的句柄
TaskHandle_t xTask1;   //任务1的句柄

void Task1(void *pvParameters) {
  //在这里可以添加一些代码,这样的话这个任务执行时会先执行一次这里的内容(当然后面进入while循环之后不会再执行这部分了)
  Data data_send;  //创建一个数据结构体用于发送数据
  data_send.sender = 1314;  //这个数据结构体的整数直接赋值为1314
  BaseType_t xStatus;  //用于状态返回在下面会用到
  BaseType_t xStatus1;
  BaseType_t xStatus2;
  int send_int = 615;
  char send_str[10] = "cx??";
  const TickType_t xTicksToWait = pdMS_TO_TICKS(100);   // 阻止任务的时间,直到队列有空闲空间 ,应该是如果发送需要阻滞等待(比如队列满了)或者别的情况需要用到的
  while(1)
  {
    vTaskDelay(1200);
    Serial.print("PRO_CPU正在运行:");
    Serial.println(xPortGetCoreID());
    Serial.print("发送任务固定在: ");
    Serial.println(xTaskGetAffinity(xTask0));    //获取任务被固定到哪里,xTask1 就是 Task0任务本身的句柄
    data_send.msg = (char *)malloc(20);  //分配所需的内存空间,并返回一个指向它的指针,里面传入的参数是SIZE。
    memset(data_send.msg, 0, 20);  //清空这个data_send,也就是上面分配的这个空间
    // 从存储区 str2 复制 n 个字节到存储区 str1。 str2就是"hello world" ,str1就是data_send.msg , strlen("hello world")就是n
    memcpy(data_send.msg, "hello world", strlen("hello world"));  
    xStatus = xQueueSendToFront( xqueue2, &data_send, xTicksToWait );  //发送data_send这个数据结构体到 xqueue2 队列
    
    xStatus1 = xQueueSendToFront( xqueue0, &send_int, xTicksToWait );  //发送send_int这个数据结构体到 xqueue0 队列
    xStatus2 = xQueueSendToFront( xqueue1, &send_str, xTicksToWait );  //发送send_str这个数据结构体到 xqueue1 队列
    if( xStatus == pdPASS && xStatus1 == pdPASS && xStatus2 == pdPASS) {
      Serial.println("send data OK");  // 发送正常 
    }
    Serial.println("******************************************************************");
  }
}
 
void Task2(void *pvParameters) {
  //  这些变量作用与上面相同,只是这里的data_get就是我们从队列里面获取的东西了
  BaseType_t xStatus;
  BaseType_t xStatus1;
  BaseType_t xStatus2;
  const TickType_t xTicksToWait = pdMS_TO_TICKS(50);  //这里就是用于取数据阻塞了,我觉得本来这种收发就不可能同步,但是应该接收来满足发送,接收速度大于发送速度才行
  Data data_get;
  int get_int;
  char get_str[10];
  while(1)
  {
    vTaskDelay(800);
    Serial.print("APP_CPU正在运行:");
    Serial.println(xPortGetCoreID());
    Serial.print("获取任务固定在:");
    Serial.println(xTaskGetAffinity(xTask1));
    xStatus = xQueueReceive( xqueue2, &data_get, xTicksToWait );  //从队列2中取一条数据
    xStatus = xQueueReceive( xqueue0, &get_int, xTicksToWait );
    xStatus = xQueueReceive( xqueue1, &get_str, xTicksToWait );
    if(xStatus == pdPASS){
      free(data_get.msg);  //释放数据结构体的字符串部分的空间
      Serial.print("获取结构体数据整数部分:");
      Serial.println(data_get.sender);
      Serial.print("获取结构体数据字符串部分:");
      Serial.println(data_get.msg);
      Serial.print("队列零的整数获取:");
      Serial.println(get_int);
      Serial.print("队列1的字符串获取:");
      Serial.println(get_str);
    }
    Serial.println("******************************************************************");
  }
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);//关闭低电压检测,避免无限重启
  Serial.begin(112500);
  delay(1000);
  Serial.print("获取Setup的优先级: ");
  Serial.println(uxTaskPriorityGet(NULL));  //优先级获取函数
  
  xqueue0 = xQueueCreate( 10, sizeof( int ) );
  xqueue1 = xQueueCreate( 10, sizeof( char[10] ) );
  xqueue2 = xQueueCreate(10, sizeof(Data));
  
  xTaskCreatePinnedToCore(Task1, "Task1", 10000, NULL, 11, &xTask0,  0);  //最后一个参数至关重要,决定这个任务创建在哪个核上.PRO_CPU 为 0, APP_CPU 为 1,或者 tskNO_AFFINITY 允许任务在两者上运行.
  xTaskCreatePinnedToCore(Task2, "Task2", 10000, NULL, 12, &xTask1,  1);  //xTaskGetAffinity(xTask1)  是可以查询到任务被固定到哪里的
  Serial.print("获取xTask0的优先级: ");
  Serial.println(uxTaskPriorityGet(xTask0));  //优先级获取函数
  Serial.print("获取xTask1的优先级: ");
  Serial.println(uxTaskPriorityGet(xTask1));  //优先级获取函数
  if(xqueue0 != NULL && xqueue1 != NULL && xqueue2 != NULL) Serial.println("开始队列测试!!!");
  Serial.println("******************************************************************");
}
 
void loop() {
}

看看结果

在这里插入图片描述

先说说上面这段代码实现了什么

我分别在两个核上创建了一个任务,一个用于向队列发送数据,一个用于向队列接收数据,而队列,我创建了三个,一个是int型的,一个是char[10],也就是定长字符串型的,还有一个是结构体型,没错,队列不仅可以实现单类型,还可以实现结构体型,结构体里面你可以自己选择用那些形式的数据。

需要注意的点:

其实很多需要注意的点,但是我在代码的注释里面写的非常非常详细了,恨不得每行都给他注释上了,所以看上面的就好,这里我给大家提炼一点:

队列的创建与初始化
xQueueHandle xqueue2;  //创建队列的句柄,详细看上面的代码
xqueue2 = xQueueCreate(10, sizeof(Data));  //这个是初始化队列,Data就是队列的数据类型,允许结构体型
//这个是从队列中读取,xqueue2是队列的句柄,data_get是我们传入的数据,xTicksToWait 是等待时间
xStatus = xQueueReceive( xqueue2, &data_get, xTicksToWait ); 
//下面这个是发送的,传入参数与上面类似
xStatus = xQueueSendToFront( xqueue2, &data_send, xTicksToWait );

最后

感谢大家哈,最近又多了两个粉丝,谢谢,我会继续写下去的,更一段时间的ESP32还要回去再把STM32的补完,之后就开始写阿里云物联网平台的,阿里云服务器可能也会开一个专栏讲讲但那是后事,而且我用那个说实话也用的不多,但是物联网平台一定要用的,所以一定会更的,好了就这样,拜拜

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(ESP32学习7)双核使用队列进行任务间通信 的相关文章

  • Elasticsearch高可用和路由规则

    文章目录 Lucene Elasticsearch ELK stack Elasticsearch集群和分片路由 高可用 Lucene 迄今为止最先进 性能最好的 功能最全的搜素引擎库 Elasticsearch 基于Apache Luce
  • flutter之Align控件

    Align控件即对齐控件 能将子控件所指定方式对齐 并根据子控件的大小调整自己的大小 对齐子控件的方式 bottomCenter 0 5 1 0 底部中心 bottomLeft 0 0 1 0 左下角 bottomRight 1 0 1 0
  • Unity机器学习2 ML-Agents第一个例子

    Unity机器学习2 ML Agents第一个例子 上一节我们安装了机器学习mlagents的开发环境 本节我们创建第一个例子 了解什么是机器学习 我们的例子很简单 就是让机器人自主移动到目标位置 不能移动到地板范围外 首先我们来简单的了解
  • SpringBoot整合ElasticSearch实现模糊查询,排序,分页,高亮

    目录 前言 1 框架集成 SpringData 整体介绍 1 1Spring Data Elasticsearch 介绍 2 框架集成Spring Data Elasticsearch 2 1版本说明 2 2 idea创建一个springb
  • js 给图片添加水印

    如何在图片上添加水印 1 把图片或者图片文件转成image元素 2 把转成的image转成canvas 3 在生成的canvas中添加水印 先看效果 1 把图片或者图片文件转成image元素 function urlToImg url re
  • 哨向 Mika & Lelush 2

    Report On Sentinels Guides of Atypical Combinations 非典型性哨兵向导结合报告 Mika x Lelush 2 亲爱的你躲在哪里发呆 上
  • Java并发(五) JUC - 类汇总和学习指南

    提示 本文对J U C进行知识体系解读 后续的文章还针对 几乎所有的核心的类以及常用的工具类作了详细的解读 如果没有时间详细阅读相关章节 可以跟着本文站在一定的高度了解JUC下包的设计和实现 同时对重要的章节提供跳转链接 您可以链接过去详读
  • 国家集训队论文分类整理

    国家集训队论文分类整理 组合数学 计数与统计 2001 符文杰 P lya原理及其应用 2003 许智磊 浅谈补集转化思想在统计问题中的应用 2007 周冬 生成树的计数及其应用 2008 陈瑜希 P lya计数法的应用 数位问题 2009
  • LPDDR4协议规范之 (四)命令和时序

    LPDDR4协议规范之 四 命令和时序 命令真值表 激活操作 读写访问操作 读前沿和后沿 突发读取操作流程 读操作时序 写前沿和后沿 突发写操作 写入均衡 待更新 命令真值表 激活操作 ACTIVATE命令由两个连续命令组成 Activat
  • 【华为OD机试 2023 B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • [创业-38]:公司、企业、组织的本质与层次

    目录 前言 公司是什么 公司的本质是什么 层次一 自身闭环系统 闭环 不是 封闭 1 1 公司是一种组织 自身的形态角度看 1 2 公司的本质是满足客户的需求 输入 存在的目的 1 3 公司的本质是解决社会和客户的问题 输入 存在的目的 1
  • 2012各大公司的C++试题

    那么多C 试题 其实最关键的是要知道考察的知识点在哪里 哎 应该好好重新看看 effective c 了 网易3道C 试题 题目1 class A public A int j i j fun1 here 在构造函数中调用了虚函数 A vo
  • EM算法步骤

    一般的 用Y表示观测随机变量的数据 Z表示隐随机变量的数据 Y和Z连在一起称为完全数据 只有观测数据Y称为不完全数据 假设给定观测数据Y 其概率分布为 P Y P Y
  • 【满分】【华为OD机试真题2023 JAVA&JS】最多提取子串数目

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 最多提取子串数目 知识点字符串统计 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 给定由 a z 26个英文小写字母组成的字符串A和B 其中A中可能存在重复字母
  • 解决urllib.error.URLError: <urlopen error [Errno 104] Connection reset by peer>

    在使用URL下载或跑模型的时候 报错urllib error URLError

随机推荐

  • 汽车线性二自由度动力学方程离散化与LQR控制原理

    汽车线性二自由度动力学方程离散化与LQR控制原理 观看B站up 忠厚老实的老王 车辆动力学视频所作 笔记
  • 【Linux】scp命令在linux和windows之间互传文件

    为了进行系统维护操作 有时需要再windows和linux或Unix系统之间互传文件 虽然有很多工具可以实现该功能 但我还是觉得命令行来的方便快捷 起初使用linux的scp命令 总是不成功 网上也没有相关介绍 经过几次努力之后 终于成功的
  • centos7上搭建CTFd(阿里云服务器版)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 阿里云搭建CTFd 前言 一 安装Python3 1 安装依赖 2 下载安装包并且编译安装 3 创建python3 pip3软连接 4 覆盖python2 5 故障修复 二
  • 企业虚拟机服务器中了lockbit3.0勒索病毒怎么办,lockbit勒索病毒解密

    虚拟机服务器在现代企业中扮演着至关重要的角色 它是一个重要的基础设施 用于支持大量的业务应用和数据存储 然而 随着网络攻击技术的不断发展 企业虚拟机服务器也面临着来自黑客的威胁 其中一种最具破坏性的攻击是勒索病毒 这种病毒能够加密企业服务器
  • 渗透测试之靶场安装与攻击机配置

    渗透测试之靶场安装与攻击机配置 文章目录 渗透测试之靶场安装与攻击机配置 搭建渗透测试攻击环境 安装渗透攻击机 docker快速搭建漏洞靶场指南 docker搭建DVWA 漏洞利用初探 Vulnapp靶场搭建 Vulfocus靶场搭建 什么
  • 【分享】golang windows 运行报错 undefined: syscall.SIGUSR1

    在跟着煎鱼大佬学习 Golang gin的时候 在优雅的重启服务篇 为了gin服务的热更新 采用了 endless fresh的方案 安装endless后无法在windows本地调试 然后报错 优雅的重启服务 地鼠文档优雅的重启服务 我不怎
  • 基于大数据分析的旅游平台的设计与实现

    基于大数据分析的旅游平台的设计与实现 摘 要 随着旅游业的发展 旅游平台作为旅游行业的重要组成部分已经逐渐受到了越来越多的关注 通过大数据分析技术为消费者提供更加精准 个性化的服务已经成为了行业关注的热点之一 在这样的背景下 基于大数据分析
  • 红明谷杯----阿尼亚

    猫哥出的题 比赛时没做出来后面做出来了 010打开图片一串数字 当时zsteg扫出来了但是没深入分析 转一次hex 再转一次发现得到一段乱码 赛后跟其他师傅交流说可以爆破找了一个在线进行乱码恢复的 得到密码为 简单的编码 根据图片的名字可以
  • 跨年烟花 html 代码汇总

    此篇汇总了一些笔者觉得好玩又可简单实现的烟花代码 多多支持大佬们的创作 烟花代码1 https blog csdn net u013343616 article details 122233674 样例 更改这里的文字可以更改弹出文字 烟花
  • Spark Standalone和yarn区别

    Spark Standalone模式提交任务 Cluster模式 spark submit master spark node01 7077 deploy mode cluster class org apache spark exampl
  • 更新pip

    项目场景 例如 当pip版本过低时 系统会提示更新命令让你更新 但是此命令经常会导致更新失败 问题描述 通过python 提示的pip更新命令更新时 会失败的问题 python m pip install upgrade pip 解决方案
  • 【计算机网络】INADDR_ANY释义

    INADDR ANY是一个常量 它指代的是一个特殊的IP地址 即0 0 0 0 在网络编程中 当一个进程需要绑定一个网络端口时 可以使用INADDR ANY来指定该端口可以接受来自任何IP地址的连接请求 具体来说 当一个进程需要监听某个网络
  • vue导出el-table中的所选项

    问题描述 最近在公司项目中需要使用导出el table中所选中的项 之前没有接触过此方面的内容 所以感觉无从下手 搜索资料后发现了解决方案 现将解决方案记录下来 方便下次使用 实现效果 解决方案 1 安装插件 npm install fil
  • DirectX9例程:绘制简单立方体

    总结至红龙书提供的立方体绘制例程代码及重要函数 d3dUtility h ifndef d3dUtilityH define d3dUtilityH include
  • ISP是什么?我们常用的ISP

    ISP全称为Internet Service Provider 即互联网服务提供商 是一种向用户提供互联网接入服务的公司或组织 它们提供的服务包括互联网接入 域名注册 网站托管等等 ISP的应用场景非常广泛 几乎所有的互联网用户都需要通过I
  • 《算法零基础100讲》 变量交换算法

    题目1 题目链接 int swapNumbers int numbers int numbersSize int returnSize numbers 0 numbers 0 numbers 1 numbers 1 numbers 0 nu
  • (已解决)pytorch错误:RuntimeError: cuDNN error: CUDNN_STATUS_EXECUTION_FAILED (安装cuda)

    RuntimeError cuDNN error CUDNN STATUS EXECUTION FAILED 原因 pytorch与cuda版本不对 也有可能是内存空间不足 可以更改虚拟空间大小 先卸载了pytorch conda unin
  • Ant Design Pro使用操作说明--(1) 搭建项目

    Antdpro Umi Dva 创建项目 之前的umi dva antd那套博客蛮多人看并且有互动 一套详细的全新升级antdpro管理系统的搭建和使用希望可以帮助到各位 这次会细分 尽量帮助你们快速解决遇到的问题 一 Ant Design
  • JS/JQ实现字符串加密成 HEX(十六进制) 字符串

    应用场景 1 数据传输 在网络通信或数据存储中 将字符串转换为十六进制格式可以确保数据的可靠传输和存储 十六进制字符串只包含数字和字母 而不涉及控制字符或其他特殊字符 因此避免了特殊字符在传输过程中引起的问题 2 数据校验 十六进制字符串可
  • (ESP32学习7)双核使用队列进行任务间通信

    这里是调用双核的方法哈 和我们单核使用的方法不兼容 因为有一些函数是不一样的 不通用 但是下一篇博文我会更一篇单核使用队列进行任务间通讯的问题 队列是什么 队列是可以从一个任务向其他任务以并发安全的方式发送消息的机制 也就是说他的目标是实现