C#串口数据处理--环形缓冲区-FIFO

2023-05-16

 一、FIFO环形缓冲区初始化

        static int MAX_BUFFER_LEN = 1024;//定义缓冲区大小
        FIFO receiveBufferManager = new FIFO(MAX_BUFFER_LEN);

 二、串口接收事件中添加写入环形缓冲

 int num = serialPort1.BytesToRead;      //获取接收缓冲区中的字节数
                byte[] received_buf = new byte[num];    //声明一个大小为num的字节数据用于存放读出的byte型数据
                serialPort1.Read(received_buf, 0, num);   //读取接收缓冲区中num个字节到byte数组中
                if (num > 0)
                {
                     receiveBufferManager.WriteBuffer(received_buf, 0,num);
                }

三、开一个线程解析数据,测试中串口以10ms的周期发送大量数据,然后在线程中以1s的速度去解析数据,数据依然不会丢失。

private void serialPort1_DataReceived1(object o)
        {
            try
            {
                byte[] freame_byte = new byte[1024];
                byte[] freame_byte1 = new byte[1024];
                while (true)
                {
                    if (receiveBufferManager.GetDataCount() > 0)
                    {
                        receiveBufferManager.ReadBuffer(freame_byte, 0, 5);
                        receiveBufferManager.ReadBuffer(freame_byte1, 0,freame_byte[2]);
                        Console.Write("数据=");
                        for (int i = 0; i < freame_byte[2]; i++)
                        {
                            Console.Write("{0:X000} ", freame_byte1[i]);
                        }
                        Console.WriteLine("");
                         receiveBufferManager.Clear(freame_byte[2]);
                    }
                    else { Console.WriteLine("缓冲区没有数据"); }
                    Thread.Sleep(1000);
               }
            }
            catch
            {

            }
        }

四、环形缓冲区实现类

public class RingBufferManager
{
    public byte[] Buffer { get; set; } // 存放内存的数组
    public int DataCount { get; set; } // 写入数据大小
    public int DataStart { get; set; } // 数据起始索引
    public int DataEnd { get; set; }   // 数据结束索引
    public RingBufferManager(int bufferSize)
    {
        DataCount = 0; DataStart = 0; DataEnd = 0;
        Buffer = new byte[bufferSize];
    }

    public byte this[int index]
    {
        get
        {
            if (index >= DataCount) throw new Exception("环形缓冲区异常,索引溢出");
            if (DataStart + index < Buffer.Length)
            {
                return Buffer[DataStart + index];
            }
            else 
            {
                return Buffer[(DataStart + index) - Buffer.Length];
            }
        }
    }

    public int GetDataCount() // 得到当前写入的字节数
    {
        return DataCount;
    }

    public int GetReserveCount() // 得到剩余的字节数
    {
        return Buffer.Length - DataCount;
    }

    public void Clear()
    {
        DataCount = 0;
    }

    public void Clear(int count) // 清空指定大小的数据
    {
        if (count >= DataCount) // 若是须要清理的数据大于现有数据大小,则所有清理
        {
            DataCount = 0;
            DataStart = 0;
            DataEnd = 0;
        }
        else
        {
            if (DataStart + count >= Buffer.Length)
            {
                DataStart = (DataStart + count) - Buffer.Length;
            }
            else 
            {
                DataStart += count;
            }
            DataCount -= count;
        }
    }

    public void WriteBuffer(byte[] buffer, int offset, int count)
    {
        Int32 reserveCount = Buffer.Length - DataCount;
        if (reserveCount >= count)                          // 可用空间够使用
        {
            if (DataEnd + count < Buffer.Length)            // 数据没到结尾
            {
                Array.Copy(buffer, offset, Buffer, DataEnd, count);
                DataEnd += count;
                DataCount += count;
            }
            else           //  数据结束索引超出结尾 循环到开始
            {
                System.Diagnostics.Debug.WriteLine("缓存从新开始....");
                Int32 overflowIndexLength = (DataEnd + count) - Buffer.Length;      // 超出索引长度
                Int32 endPushIndexLength = count - overflowIndexLength;             // 填充在末尾的数据长度
                Array.Copy(buffer, offset, Buffer, DataEnd, endPushIndexLength);
                DataEnd = 0;
                offset += endPushIndexLength;
                DataCount += endPushIndexLength;
                if (overflowIndexLength != 0)
                {
                    Array.Copy(buffer, offset, Buffer, DataEnd, overflowIndexLength);
                }
                DataEnd += overflowIndexLength;                                     // 结束索引
                DataCount += overflowIndexLength;                                   // 缓存大小
            }
        }
        else 
        {
            // 缓存溢出,不处理
        }
    }

    public void ReadBuffer(byte[] targetBytes,Int32 offset, Int32 count) 
    {
        if (count > DataCount) throw new Exception("环形缓冲区异常,读取长度大于数据长度");
        Int32 tempDataStart = DataStart;
        if (DataStart + count < Buffer.Length)
        {
            Array.Copy(Buffer, DataStart, targetBytes, offset, count);
        }
        else 
        {
            Int32 overflowIndexLength = (DataStart + count) - Buffer.Length;    // 超出索引长度
            Int32 endPushIndexLength = count - overflowIndexLength;             // 填充在末尾的数据长度
            Array.Copy(Buffer, DataStart, targetBytes, offset, endPushIndexLength);
            
            offset += endPushIndexLength;
            
            if (overflowIndexLength != 0)
            {
                Array.Copy(Buffer, 0, targetBytes, offset, overflowIndexLength);
            }
        }
    }


    public void WriteBuffer(byte[] buffer)
    {
        WriteBuffer(buffer, 0, buffer.Length);
    }

}

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

C#串口数据处理--环形缓冲区-FIFO 的相关文章

  • Ubuntu上使用Qt Creator编译、下载PX4代码

    文章目录 一 创建工程文件二 Qt 加载工程文件三 工程的配置四 编译工程五 下载程序六 连接QGC验证 一 创建工程文件 在命令行执行以下几条命令 xff1a span class token function cd span src F
  • ROS1学习笔记:launch启动文件的使用方法

    参考B站古月居ROS入门21讲 xff1a launch启动文件的使用方法 基于VMware Ubuntu 20 04 Noetic版本的环境 文章目录 一 launch的文件结构二 launch的文件语法2 1 根元素2 2 参数设置2
  • ROS1学习笔记:常用可视化工具的使用(ubuntu20.04)

    参考B站古月居ROS入门21讲 xff1a 常用可视化工具的实现 基于VMware Ubuntu 20 04 Noetic版本的环境 文章目录 一 日志输出工具 xff1a rqt console二 绘制数据曲线 xff1a rqt plo
  • 笔记(STM32篇)day1——工程创建、操作寄存器点灯

    目录 一 STM32F103VET6 二 创建工程 1 主要文件 2 生成文件 三 操作寄存器点灯 前言 这一年 xff0c 从调剂到各种找工作面试 去实习 xff0c 感受总结下来就是 出走半生 xff0c 归来仍是萌新 xff0c 作为
  • 手把手教CMake编译Qt5工程

    一 新建CMakeLists txt 可以在工程目录下新建一个名为CMakeLists txt文件 xff0c 亦或是 xff0c 在Qtcreator中 xff0c 右键项目 xff0c 添加新文件 xff0c 选择General中的Em
  • Arduino学习篇 FreeRtos的使用

    ESP32 Arduino中的FreeRTOS使用 在platformio中不需要引入FreeRTOS的头文件 xff0c 直接可用 FreeRTOS使用第一步 xff1a 任务的创建与删除 下面的代码启用了两个任务 xff0c 并且在执行
  • 创建Ubuntu18.04的工作空间、环境变量与增强功能

    一 编译环境变量 在主目录旁显示隐藏文件 xff0c 找到 bashc文件打开来 在最后面加上以下几句代码 source opt ros melodic setup bash source catkin ws devel setup bas
  • Linux内核下gitee的使用

    一 什么是git git是一个开源的分布式版本控制系统 xff0c 用于敏捷高效地处理任何或小或大的项目 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件 Git 与常用的版本控
  • c++ 中 char 与 string 之间的相互转换问题

    首先必须了解 xff0c string可以被看成是以字符为元素的一种容器 字符构成序列 xff08 字符串 xff09 有时候在字符序列中进行遍历 xff0c 标准的string类提供了STL容器接口 具有一些成员函数比如begin end
  • 四旋翼 PID 控制

    文章目录 一 PID 原理二 四旋翼串级双闭环 PID 控制1 外环2 内环 一 PID 原理 偏差控制 xff0c 利用目标值 xff08 期望值 xff09 与实际测量值构成的偏差 xff08 误差 xff09 对被控对象进行线性的控制
  • 串口输出乱码问题的解决方法汇总(持续更新):

    平时工作中程序员在调试时总会用到串口打印数据以及一些标志位查看程序是否出现问题 但是在使用时总会遇到各种各样的问题 xff0c 最常见的就是输出乱码问题 xff08 指的是有收到数据但数据显示的是一堆不认识的汉字或字符 xff09 xff0
  • 无人机运动学控制中的坐标系,及惯性坐标系与机体坐标系之间的矩阵转换 欧拉角

    一 无人机控制中的坐标系 无人机运动学中 xff0c 有三种需要了解的坐标系 1 1 地球中心坐标系 xff08 ECEF xff09 地球中心坐标系 xff0c 即坐标系原点位于地心 X轴通过格林尼治线和赤道线的交点 xff0c 正方向为
  • 关于如何用Cmake配置opencv C++环境

    基于 opencv3 4 6 在vs 2017 中的实现 首先百度搜搜并安装opencv3 4 6 下载链接 xff1a https nchc dl sourceforge net project opencvlibrary 3 4 6 o
  • cmake(六)Cmake添加工程子目录

    重点 xff1a 39 cmake3 39 和 39 make 39 命令 39 输出 39 的 39 深刻解读 39 备注 xff1a 当前阶段暂时不使用 39 IDE 39 工具 先 39 熟悉各指令 39 一 ADD SUBDIREC
  • 【笔记】从零开始制作自己的Pascal VOC数据集

    1 Pascal VOC 数据集简介 1 1 概要 图像分类和目标检测顶会论文的实验部分总是可以看到基于Pascal VOC数据集的算法结果分析 xff0c 它为图像分类 目标检测和图像分割都提供了优秀的数据支撑 xff0c 2005年到2
  • 使用Visual Studio 2022运行C++代码

    使用Visual Studio 2022运行C 43 43 代码 1 打开VS 2022 xff0c 创建新项目 2 安装多个工具和功能 3 选中 使用C 43 43 的桌面开发 和 通用Windows平台开发 xff0c 点击修改 xff
  • Cmake系列(三) 在 CMakeLists.txt 引入第三方so库

    将 so 库和头文件拷贝到对应的目录 app src main jniLibs arm libxxx so 修改 CMakeLists txt 文件 第三方so库 这里和之前在第二步中介绍的创建一个新的原生库类似 xff0c 区别在于最后一
  • git checkout 命令详解

    在日常的git操作中 xff0c git checkout 检出 xff0c 是我们的常用命令 最为常用的两种情形是创建分支和切换分支 在下面的命令中 xff0c 使用了一些简写 xff0c 在这里说明一下 xff1a git st git
  • 对简单字符串的排序整理(简单的2种方法)

    一 用sort对字符串排序 1 sort可以对string排序 我在做题的时候发现我用sort对string排序的语句判错 我最开始写的代码是 string s cin gt gt s int len 61 s length sort s
  • python的print输出如何不换行

    在python的中使用的print函数 xff0c 如果只是输出内容 xff08 包括整型数 xff0c 浮点型 xff0c 字符串等 xff09 xff0c 那么在这一行语句结束之后 xff0c print会自动换行 span class

随机推荐