Day3--流媒体缓存、消息缓存(重要)、直接任务通知

2023-05-16

FreeRTOS 10以后引入了一个新的数据类型就是 Stream Buffer它和Queue最大的不同就是,Stream Buffer读写的大小没有限制,而Queue是预设值好固定的值。Stream Buffer 流媒体缓存顾名思义它的受众对象就是 流媒体 比如MP3,视频,在线电台等。

需要设置最小“一帧”的大小,播放一个声音最少需要8个字节。设置xTruggerLevel = 8

流媒体的优点:输入输出数据的大小不受限制

   程序:  使用Stream Buffer 对流媒体数据,在任务间进行传输

          流媒体,读和写的大小都没有任何的限制

          读和写的大小可以不一致, 比如写入100 bytes, 可以分成两次每次50 bytes读取出来

   注意:  适合于一个任务写,另外一个任务读

          不适合多任务读写

          如果必须要用在多任务的读写,请将内容放入CRITICAL SECTION

          可以使用 MUTEX 或者 TASK Notification

/*
   程序:  使用Stream Buffer 对流媒体数据,在任务间进行传输
          流媒体,读和写的大小都没有任何的限制

          读和写的大小可以不一致, 比如写入100 bytes, 可以分成两次每次50 bytes读取出来

   注意:  适合于一个任务写,另外一个任务读
          不适合多任务读写

          如果必须要用在多任务的读写,请将内容放入CRITICAL SECTION
          可以使用 MUTEX 或者 TASK Notification
   公众号:孤独的二进制

   API:
*/

//不要忘记include stream_buffer.h
#include <freertos/stream_buffer.h>

StreamBufferHandle_t xStreamMusic = NULL; //创建一个 Stream Buffer 的 handler


void downloadTask(void *pvParam) { //下载音乐

  String music;
  size_t xBytesSent; //The number of bytes written to the stream buffer.

  while (1) {

    //从网络下载音乐,放一些随机的延迟
    for (int i = 0; i < random(20, 40); i++) vTaskDelay(1);
    music = randomMusic(); //随机生成一些数据

    xBytesSent = xStreamBufferSend( xStreamMusic,
                                    (void *)&music,
                                    sizeof(music),
                                    portMAX_DELAY);

    if ( xBytesSent != sizeof( music ) ) {
      Serial.println("警告: xStreamBufferSend 写入数据出错");  //Optional
    }

    vTaskDelay(100);
  }

}

void playBackTask(void *pvParam) { //解码并且播放

  size_t xReceivedBytes; //The number of bytes read from the stream buffer.
  size_t xReadBytes = 8*10-1;
  String music;

  while (1) {
    xReceivedBytes = xStreamBufferReceive( xStreamMusic,
                                           ( void * ) &music,
                                           xReadBytes,
                                           portMAX_DELAY );
    if ( xReceivedBytes > 0 )
    {
      decode(music);
    }

  }
}


void monitorTask (void * pvParam) { //对 streamBuffer进行监控
  size_t xAvailable, xUsed;
  bool isFull;
  while (1) {

    //Queries a stream buffer to see if it is full.
    if (xStreamBufferIsFull(xStreamMusic) == pdTRUE) Serial.println("xStreamMusic 已满");

    //Queries a stream buffer to see how much data it contains
    xUsed =  xStreamBufferBytesAvailable(xStreamMusic);

    //Queries a stream buffer to see how much free space it contains
    xAvailable = xStreamBufferSpacesAvailable(xStreamMusic);

    char msg[40];
    sprintf(msg, "xStreamBuffer已使用 %d 字节", xUsed);
    Serial.println(msg);
    sprintf(msg, "xStreamBuffer可用空间为 %d 字节", xAvailable);
    Serial.println(msg);

    vTaskDelay(2000);

  }
}


void setup() {
  Serial.begin(115200);

  //Stream Buffer的最大尺寸,如果超出可能内存空间,那么创建Stream Buffer就会失败
  const size_t xStreamBufferSizeBytes = 540;
  //Trigger Level - Stream Buffer内数据超过这个数值,才会被读取
  const size_t xTriggerLevel = 8;
  xStreamMusic = xStreamBufferCreate(xStreamBufferSizeBytes, xTriggerLevel);

  if ( xStreamMusic == NULL )
  { //内存不过,无法创建Stream Buffer
    Serial.println("UNABLE TO CREATE STREAM BUFFER");
  }
  else
  {
    xTaskCreate(downloadTask, "Download Music", 1024 * 8, NULL, 1, NULL); //下载音乐
    xTaskCreate(playBackTask, "Playback Music", 1024 * 8, NULL, 1, NULL); //解码播放音乐
    xTaskCreate(monitorTask, "Monitor Stream Buffer", 1024 * 8, NULL, 1, NULL); //对Stream Buffer进行监控
  }

  vTaskDelete(NULL);  //setup 和 loop 这个loopBack任务没用了,自宫了
}

void loop() {

}

消息缓存(重要)

Message Buffer是基于Stream Buffer的。只是在每一次发送数据的时候多了四个字节的空间用于存放消息的大小。根据这个消息大小,读取放就可以一次读取出全部消息的内容。

在每一次的数据里面都会加4个字节,用于存放数据大小

用处:消息的传输。任务1对GPS数据进行读取,任务2进行LCD显示。

很适合 串口 接收和发送数据,每次的大小不定,但是接受和发送的数据量需要相同

注意:在每次发送数据都会自动加4个字节,因此读的数据和写的数据相同。

/*
   程序:  Message Buffer
          基于Stream Buffer上实现的, 在传输的时候用4个字节记录了sent的内容大小
          这样子读取的话,也可以一次读取对应大小的数据
          所以很适合 串口 接收和发送数据,每次的大小不定,但是接受和发送的数据量需要相同
   公众号:孤独的二进制
*/

//不要忘记include message_buffer.h
#include <freertos/message_buffer.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

MessageBufferHandle_t xMessageBuffer = NULL;

void readGPS(void *pvParam)   
{
  size_t xBytesSent; // The number of bytes written to the message buffer.
  String gpsInfo;
  while (1)
  {
    gpsInfo = randomGPS(); //随机发送不同长度的信息
    xBytesSent = xMessageBufferSend(xMessageBuffer,
                                    (void *)&gpsInfo,
                                    sizeof(gpsInfo),
                                    portMAX_DELAY);// 如果内容已经满了,则处于堵塞状态,此时不占用CPU内存

    if (xBytesSent != sizeof(gpsInfo))
    {
      Serial.println("危险: xMessageBufferSend 发送数据不完整");
    }
    vTaskDelay(3000);
  }
}

void showGPS(void *pvParam)
{
  size_t xReceivedBytes;
  String gpsInfo;
  const size_t xMessageSizeMax = 100;
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("   GPS INFO"); // clear this line
  while (1)
  {
    xReceivedBytes = xMessageBufferReceive(xMessageBuffer,
                                           (void *)&gpsInfo,
                                           xMessageSizeMax, // 设置最大读取的熟练多少,跟显示屏可以显示多少内容有关
                                           portMAX_DELAY);

    if (xReceivedBytes > 0)
    {
      gpsDecoder(gpsInfo); //解码,并且显示到屏幕上
    }

    vTaskDelay(1000);
  }
}

void monitorTask(void *pvParam)
{ //对 streamBuffer进行监控
  size_t xAvailable, xUsed;
  bool isFull;
  while (1)
  {

    // Queries a stream buffer to see if it is full.
    if (xMessageBufferIsFull(xMessageBuffer) == pdTRUE)
      Serial.println("xMessageBuffer 已满");

    // Queries a stream buffer to see how much free space it contains
    xAvailable = xMessageBufferSpacesAvailable(xMessageBuffer);

    char msg[40];
    sprintf(msg, "xMessageBuffer可用空间为 %d 字节", xAvailable);
    Serial.println(msg);

    vTaskDelay(1000);
  }
}

void setup()
{
  Serial.begin(115200);
  const size_t xMessageBufferSizeBytes = 100;  // 创建消息缓存大小,因为每次发送数据自动加4个字节,所以不需要加****
  xMessageBuffer = xMessageBufferCreate(xMessageBufferSizeBytes);

  if (xMessageBuffer == NULL)
  {
    Serial.println("Unable to Create Message Buffer");
  }
  else
  {
    xTaskCreate(readGPS, "Read GPX", 1024 * 4, NULL, 1, NULL);
    xTaskCreate(showGPS, "Show GPX", 1024 * 4, NULL, 1, NULL);
    xTaskCreate(monitorTask, "Monitor Message Buffer", 1024 * 8, NULL, 1, NULL); //对Stream Buffer进行监控
  }
}

void loop()
{
  //   String gpsinfo = randomGPS();
  //   Serial.println(gpsinfo);
  //  gpsDecoder(gpsinfo);
  //   delay(1000);
}

直接任务通知

Direct Task Notification是FreeRTOS 10版本以后的最重要的一个功能。他可以实现大部分二进制信号量,计数信号量,事件组,邮箱等等的功能。而且速度快45%,占用更少的内存。

总结

采用CPU分时的方法,1s内执行一千次ticks,达到实时的效果

任务传单参数/多参数,只能用指针的方式,用指针不用进行数据的复制,节省内存空间,采用结构体进行多参数的传递

创建任务注意事项:core0运行蓝牙和WIFI

内存管理:分配内存空间尽量大一点,1024* N 字节

看门狗与任务优先级结合使用,避免一直工作在某一个任务上

任务的绝对频率,应用在周期性的任务上,时间更加准确

软件定时器:分为一次性的和周期性的定时器

保护数据安全(线程安全,还有多任务全局变量Mutex):队列单数据、流媒体缓存和消息缓存(后两者是freertos最新的版本10.0才有的)

队列单数据:在创建队列时,已经规定队列的大小,放数据和取数据,数据结构必须一样

流媒体缓存:放的数据和取的数据大小可以不一样,比如MP3、MP4

消息缓存:基于流媒体缓存,第一次放的X,则第一次读出的也为X,每一次的放入可以不一样大,但是每一次的读出一样大(适合于串口的数据读取,可以采用Mutex对数据进行保护)

当一个资源被N(≥2)个资源访问,必须采用Mutex对线程进行保护

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

Day3--流媒体缓存、消息缓存(重要)、直接任务通知 的相关文章

  • git常见问题

    git常见错误 1 在git pull时遇到fatal refusing to merge unrelated histories错误 意思是 xff1a 拒绝合并不相关的分支 表示要合并的本地分支和远程分支是相互独立而不是相关联的 我的情
  • PID 控制器

    本文参考 xff1a 从不懂到会用 xff01 PID从理论到实践 哔哩哔哩 bilibili 目录 1 PID控制器入门 1 1 PID控制器的引入 1 2 PID控制器适用系统 1 3 PID控制器宏观意义 2 PID控制器的必备知识
  • Linux - 第11节 - 网络入门

    目录 1 计算机网络背景 1 1 网络发展 1 2 认识 34 协议 34 2 网络协议初识 2 1 协议分层 2 2 OSI七层模型 2 3 TCP IP五层 xff08 或四层 xff09 模型 3 网络传输基本流程 3 1 同局域网的
  • 【经典问题:汉诺塔】C语言编写程序实现汉诺塔问题——函数递归

    汉诺塔 xff08 Tower of Hanoi xff09 xff0c 又称河内塔 xff0c 是一个源于印度古老传说的益智玩具 大梵天创造世界的时候做了三根金刚石柱子 xff0c 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘 大梵
  • 1.语音增强技术概述

    一 语音增强发展历史 1987年 xff1a Lim和Oppenheim发表语音增强的维纳滤波方法 xff1b 1987年 xff1a Boll发表谱减法 xff1b 1980年 xff1a Maulay和Malpass提出软判决噪声一直方
  • PCB软件对比分析(AD、Pads、Allegro)

    文章目录 前言一 国内的EDA软件市场二 Altium三 Mentor四 Candence总结 前言 今天来说一说国内用的最多的三款PCB软件对比 一 国内的EDA软件市场 国内的EDA软件几乎被三家瓜分 1 Altium 2 Canden
  • (二)立创EDA之新建工程,原理图,PCB

    文章目录 前言一 界面介绍二 工程广场介绍三 新建工程3 1 修改图纸属性 四 基本的操作介绍4 1 添加器件4 2 连接导线4 3 添加插针4 4 查看封装4 5 修改封装 五 原理图转PCB5 1设置PCB高亮显示元器件5 2 布局传递
  • stm32mp157 wm8960音频驱动调试笔记

    这次调试wm8960音频驱动遇到了好多的坑 xff0c 研究好几天终于调试好了 驱动调试步骤 驱动能不能成功加载是调试的第一大步骤 xff0c 也是最关键的步骤之一 1 查看硬件原理图 2 打开对应的设备树 xff08 stm32mp157
  • ROS发布者(Publisher)和订阅者(Subscriber)的python编程实现(讲解超级详细)

    有时候想想 xff0c 国内有些资源确实比较稀缺 xff0c 但是我们一样不会落后 xff01 学习python和ROS这么久了 xff0c 一直很少去实战 xff0c 另外看到基于python编程的ROS话题通信教程实在是稀缺了 xff0
  • C#工控上位机——框架

    C 工控上位机 第一部分 xff1a UI模块 先点击一下Panel xff0c 在点击一下屏幕 先选中Panel xff0c 在进行属性设置 图标连接 嵌入式窗体 设置按键的事件 using
  • docker镜像启动es/kibana

    下载镜像elasticsearch docker search elasticsearch docker pull elasticsearch 启动镜像 docker run name my elasticsearch p 9200 920
  • 虚拟串口的使用

    虚拟串口的使用
  • 修改闭包内使用的外部变量

    修改闭包内使用的外部变量的错误示例 定义一个外部函数 def func out num1 定义一个内部函数 def func inner num2 这里本意想要修改外部num1的值 xff0c 实际上是在内部函数定义了一个局部变量num1
  • 嵌入式软件面试题

    CSDN的小伙伴们 xff0c 我是林君 今天给小伙伴们分享一些嵌入式软件开发工程师的校招面试题 企业校招对基础考察较多 其次 xff0c 在校参加的相关比赛 xff0c 项目经历 我在生病前 xff0c 面试了一周 xff0c 收到八九个
  • 嵌入式软件工程师技术等级

    1 初级 xff1a 8051或其他单片机 xff0c UCOS xff0c I C xff0c SPI xff0c UART 汇编和C语言能力一般 xff0c 系统集成能力弱 2 中级 xff1a 在初级的基础上 xff0c ARM MI
  • FreeRTOS之动态方法任务创建和删除实验

    一 实验设计 start task xff1a 用来创建其他两个任务 task1 task 当此任务运行5次就调用vTaskDelete 删除任务task2 task task2 task 此任务为普通的应用任务 一 宏定义 任务优先级 d
  • 人工智能研究主要有哪三大学派,其特点是什么?

    人工智能研究主要有哪三大学派 xff0c 其特点是什么 xff1f xff08 1 xff09 符号主义 xff1a 又称为功能模拟学派 xff0c 主要观点认为智能活动的基础是物理符号系统 xff0c 思维过程是符号模式的处理过程 其特点
  • FreeRTOS入门

    目录 一 任务要求二 FreeRTOS移植1 简介2 参考教程3 多任务程序管理实现4 执行结果 三 总结 一 任务要求 在STM32下完成一个基于FreeRTOS的多任务程序 xff0c 执行3个周期性task xff0c 具体任务不限
  • 2021年全国大学生电子设计大赛F题——智能送药小车,全方位解决方案+程序代码(详细注释)山东赛区国奖

    目录 1 赛题及硬件方案分析 xff1a 2 用到的主要器件清单 xff1a 3 各部分思路及代码实现 1 小车舵机 马达驱动 2 蓝牙通信 3 单片机与OpenMV的串口通信 4 单片机与OpenMV的通信协议 5 单片机main文件中的
  • C++学习小记之代码重用问题(1)

    C 43 43 Primer Plus第六版第14章程序清单14 2给的示例代码中有以下两段代码 xff1a double amp Student operator int i return scores i double Student

随机推荐

  • 出现“ ‘xxx‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。”的一个解决方法

    XXX 不是内部或外部命令 xff0c 也不是可运行的程序或批处理文件 前提是已经安装成功某一个插件 有时候 xff0c 我们想用cmd xff08 以管理员身份运行 xff09 执行命令的时候 xff0c 总会出现 XXX 不是内部或外部
  • RK算法分析

    这一节介绍一下由Rabin和Karp提出的RK算法 1 xff0c RK算法的基本思想 HASH xff01 如果两个字符串hash后的值不相同 xff0c 则它们肯定不相同 xff1b 如果它们hash后的值相同 xff0c 它们不一定相
  • Xilinx ZYNQ FreeRTOS+Tracealyzer(移植)

    PL端配置 使用ZYNQ IP Core 打开串口 网口等所需接口 新手注意 xff1a 需要生成bit文件后 xff0c 并输出相应硬件平台 xff0c 网上教程很多 xff0c 请参考其它教程 PS端配置 1 创建任务 xff0c 注意
  • Openmv学习day2——AprilTag

    仅作为个人学习 xff0c 原文地址 xff1a 链接 link AprilTag的简介 AprilTag是一个视觉基准系统 xff0c 可用于各种任务 xff0c 包括AR xff0c 机器人和相机校准 这个tag可以直接用打印机打印出来
  • JS进行简单的表单验证(附详细代码)

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 一 JS表单验证是什么 xff1f 一 JS表单验证需求分析 xff1f 三 表单验证所需事件设置from表单及其文本框 xff
  • FreeRTOS学习(三)FreeRTOS任务基础知识

    FreeRTOS任务基础知识 1 FreeRTOS任务特性2 FreeRTOS的任务状态3 任务优先级4 任务调度方式5 任务控制块6 任务堆栈 1 FreeRTOS任务特性 特性1 xff1a 任务数量没有限制 xff0c 想要创建多少个
  • 如何写串口通信

    1 初始化串口 void USART INIT void GPIO InitTypeDef GPIO InitStructure 使能USART1 RCC APB2PeriphClockCmd RCC APB2Periph USART1 E
  • 树莓派WiFi连接问题及网页打开问题的解决

    树莓派WiFi连接问题及网页打开问题的解决 一 问题描述 前一段时间在网上买了一个树莓派 4b计划做一个人脸识别的智能锁 xff0c 前一段时间整赶上期末考试 xff0c 挤时间做了做人脸识别以及人体红外感知模块 xff0c 大致能简单实现
  • windows双系统如何删除ubuntu系统并重装

    电脑装有windows和Ubuntu双系统 xff0c 当需要重装Ubuntu时 xff0c 需要先卸载掉已经安装的Ubuntu系统 博主电脑安装的是Windows10和Ubuntu20 04LTS 现在需要卸载Ubuntu20 04 xf
  • 全网最全的MCU面试经(基于STM32F103)

    免责声明 提示 xff1a 写本文章的缘由 xff1a 本人在秋招时复习STM32有关的知识点 xff0c 便顺势记录下来 本文章的知识均属于各大论坛的大佬回答 xff0c 其中也有我的一些补充 xff0c 本文主要以自己对STM32的理解
  • Quartus II和Modelsim初学踩坑笔记

    Quartus II和Modelsim初学踩坑笔记 1 软件安装 网上有关软件安装的教程已经足够多了 xff0c 这里不再赘述 xff0c 但我要提醒的一点是 xff0c 不要把软件和之后创建的项目工程放在中文路径下面 本文使用的软件环境是
  • HDLBits刷题记录--Modules:Hierarchy

    HDLBits刷题记录 Modules Hierarchy Module 电路图 xff1a 代码 xff1a module top module span class token punctuation span input a span
  • C++中SORT函数使用方法

    一 sort函数 1 sort函数包含在头文件为 include lt algorithm gt 的c 43 43 标准库中 xff0c 调用标准库里的排序方法可以实现对数据的排序 xff0c 但是sort函数是如何实现的 xff0c 我们
  • Window下LaTex+VS Code的配置

    目录 前言 一 软件下载二 软件安装1 TexLive安装2 VS Code及插件安装 三 配置 VS Code四 简单测试一下五 进阶操作及可能遇到的问题1 前向搜索和反向搜索2 编译带参考文献的 tex文件 前言 考虑本文受众有新手小白
  • 与 vmx86 驱动程序的版本不匹配解决方法

    一个新手可能遇到的问题 第一次安装完VMware后 xff0c 启动时可能会遇到问题 xff1a 与 vmx86 驱动程序的版本不匹配 预期为xxx 实际为 xxx 驱动程序 vmx86 sys的版本不正确 如下图 xff1a 解决方法 x
  • 汽车电子系统知识积累

    文章目录 前言一 汽车电子系统的分类1 电子控制汽车电子控制系统2 电子控制车载汽车电子系统 二 分类及详述1 动力2 底盘3 车身4 娱乐 总结 前言 汽车电子系统是以汽车电子技术为基础的汽车结构 一 汽车电子系统的分类 按照电子系统对汽
  • Jetson Xavier NX 学习(一),安装sd卡镜像

    Jetson Xavier NX 学习 xff08 一 xff09 xff0c 安装sd卡镜像 说明个人说明了解JetPack SDK下载镜像将图像写入microSD卡启动查看设置 说明 Jetson Xavier NX可为运行现代AI工作
  • 服务器ssh远程连接失败

    服务器远程ssh连接失败解决方案 查看ssh服务状态 systemctl status sshd service 正常应该是下图情况 xff1a xff08 running xff09 绿色即为正常状态 在这里插入图片描述 如果正常查看后面
  • Day1--FreeRTOS简介及多任务点灯、多任务传参、Mutex

    实时操作系统 xff08 Real Time Operating System xff0c 简称RTOS xff09 Arduino任务执行流程 xff1a 单线程执行任务 RTOS xff1a 可以同时执行所有Task xff0c 每个任
  • Day3--流媒体缓存、消息缓存(重要)、直接任务通知

    FreeRTOS 10以后引入了一个新的数据类型就是 Stream Buffer 它和Queue最大的不同就是 xff0c Stream Buffer读写的大小没有限制 xff0c 而Queue是预设值好固定的值 Stream Buffer