使用循环缓冲区从串口读取数据 [英] Using circular buffer for reading data from serial port

查看:102
本文介绍了使用循环缓冲区从串口读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用byte []存储串口发送的响应。



但需要将数据存储到循环缓冲区(使用GitHub上提供的循环缓冲区)并作为数据进入



1.如果数据未完全收到则丢弃它。

2 。取一些数据

3.并解析它就像E0意味着开始数据。





基本上是我正在寻找循环缓冲操作吗?



我尝试过:



这是循环缓冲区



I am currently using an byte[] to store the response send by the serial port.

But the need is to store the data into an circular buffer (using the Circular Buffer provided on GitHub) and as data come into it

1.if data is not fully received discard it.
2.take some data
3.and parse it like E0 means start of data.


Basically the Circular buffer operation is what I am looking for?

What I have tried:

Here is the Circular buffer

using CircularBuffer;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace SerialPortCommunicationWithStateMachines
{
    public class DataReceiveHandle
    {
        public static int MAX_PACKET_LENGTH = ChannelDataCount.count;

        public bool newData = false;

        public int rxOffset = 0;

        public byte[] rxBuffer = new byte[MAX_PACKET_LENGTH];

      
        public byte[] rxPackage = new byte[MAX_PACKET_LENGTH];

     

        public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
           // var xbuffer = new CircularBuffer<byte>(10);
            if (e.EventType != SerialData.Chars) return;

            SerialPort port = (SerialPort)sender;

            

            int bytesCount = port.BytesToRead;
          
            port.Read(rxBuffer, rxOffset, bytesCount);


            rxOffset = rxOffset + bytesCount;

            if (HasCompletePackage())
            {
                Console.WriteLine("Full packet has been received");
                rxBuffer.CopyTo(rxPackage, 0);
                rxOffset = 0;

                newData = true;
            }

            if (newData == true)
            {
                if (rxPackage[0] == 224
                    && rxPackage[1] == 242
                    && rxPackage[2] == 1
                    && rxPackage[3] == 0
                    && rxPackage[4] == 60
                    && rxPackage[5] == 37
                    && rxPackage[6] == 133
                    && rxPackage[7] == 0
                    && rxPackage[8] == 0)
                {
                    Console.WriteLine("Header Content is:");
                    for (int i = 0; i <= 8; i++)
                    {
                        Console.WriteLine(rxPackage[i]);
                    }
                }

                Console.WriteLine("Message Content is: ");

                for (int i = 9; i < MAX_PACKET_LENGTH; i++)
                {
                    Console.WriteLine(rxPackage[i]);
                }

            }


        }
        private bool HasCompletePackage()
        {
            if (rxOffset == 60)
                return true;
            else
                return false;
        }
    }
    }

推荐答案

注意:

已回答这是关于这个问题的重新发布,但也会在这里添加它,因为重新发布可能会被删除。还添加了一些更多信息。



我仍​​然认为这里不需要环形缓冲区。



你已经有了一个缓冲区: rxBuffer 。要设置一个环形缓冲区,您只需相应地使用 rxOffset 处理写访问:

Note:
Answered this on a repost of this question but going to add it here as well because the repost might get deleted. Added also some more information.

I still don't think that there is a need for a ring buffer here.

You already have a buffer: rxBuffer. To make that a ring buffer all you have to do is handling the write access using rxOffset accordingly:
// Check if we have to wrap to the begin of the buffer
int bytesToRead = min(bytesCount, rxBuffer.Length - rxOffset);
port.Read(rxBuffer, rxOffset, bytesToRead); 
rxOffset += bytesToRead;
if (rxOffset >= rxBuffer.Length)
{
    bytesToRead = bytesCount - bytesToRead;
    port.Read(rxBuffer, 0, bytesToRead); 
    rxOffset = bytesToRead;
}

现在你有一个环形缓冲区。根据具体情况,您可以实现一个具有另一个类级别变量的阅读器,该变量定义当前读取位置(并检查 rxOffset 不会超出该读取位置)。 />


但是实施上述内容您可能会发现它无法解决您的问题。您的问题实际上不是如何实现环形缓冲区,而是定义如何处理(处理)接收数据。这是在编写任何代码行之前必须完成的任务。一旦你定义了它,你就可以考虑可能的实现。



假设你有一个开始序列和一个长度字段,每次接收都会这样做:

  • 如果到目前为止未找到,请找到起始序列

  • 如果检测到开始并且已收到足够的后续字节(存在长度字段),得到那个

  • 如果长度存在,则接收直到收到所有包字节

  • 如果完整的包数据有已收到,处理数据

  • Now you have a ring buffer. Depending on what to do with that you might implement a reader having another class level variable defining the current read position (and checking that rxOffset will not overrun that read position).

    But implementing the above you might recognise that it does not solve your problem. Your problem is actually not how to implement a ring buffer but to define how the received data has to be handled (processed). That is a task which must be done before writing any line of code. Once you have defined that, you can think about possible implementations.

    Assuming that you have a start sequence and a length field do this with each receiving:

    • Locate the start seqence if not detected so far
    • If start detected and enough following bytes has been received (length field present), get that
    • If length present, receive until all package bytes has been received
    • If a complete package data has been received, process the data

    • Quote:

      没有C#中的循环/环形缓冲区的默认实现

      there is no default implementation of circular/Ring Buffer in C#

      您认为队列类 [ ^ ]是?

      And what do you think the Queue Class[^] is?

      Quote:

      这个class将队列实现为循环数组。存储在队列中的对象在一端插入并从另一端移除。



      当您需要临时存储信息时,队列和堆栈非常有用;也就是说,您可能希望在检索其值后丢弃该元素。如果您需要以与存储在集合中相同的顺序访问信息,请使用队列...

      This class implements a queue as a circular array. Objects stored in a Queue are inserted at one end and removed from the other.

      Queues and stacks are useful when you need temporary storage for information; that is, when you might want to discard an element after retrieving its value. Use Queue if you need to access the information in the same order that it is stored in the collection ...


      这篇关于使用循环缓冲区从串口读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆