如何将数据从串口数据保存到环形缓冲区? [英] How do I save data from serial port data to ring buffer?

查看:129
本文介绍了如何将数据从串口数据保存到环形缓冲区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个用于串口通信的桌面应用程序。连接到串口的硬件以数据包的形式发送数据。



但该数据包中的字节数是未知的,因此使用环形缓冲区。



C#中没有循环/环形缓冲区的默认实现,这就是为什么我使用GitHub上提供的一个https:/ /github.com/xorxornop/RingBuffer/blob/master/PartiallyConcurrent/RingBuffer.cs



我希望将数据保存到收到的Ring Buffer中,然后解析它(如检查标头字节,设备ID,状态字节等)如果它不在那里然后丢弃它。



我尝试了各种实现但是无法获得正确实施。



我尝试过:



I am developing an desktop application for serial port communication.The hardware connected to serial port sends the data in packet.

But the numbers of bytes in that packet is unknown,hence use of ring buffer.

there is no default implementation of circular/Ring Buffer in C#,that's why i am using one provided on GitHub https://github.com/xorxornop/RingBuffer/blob/master/PartiallyConcurrent/RingBuffer.cs

I want to save data into Ring Buffer as received and then parse it(like checking for header bytes,for device id,for status byte etc) and if it's not there then discard it.

I have tried various implementation but was unable to have an correct implementation.

What I have tried:

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

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

        public static bool newData = false;

        public static int rxOffset = 0;
        public static int rxWrite = 0;
        public static int rxRead = 0;
    
        public static byte[] rxBuffer = new byte[MAX_PACKET_LENGTH];

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

        public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            if (e.EventType != SerialData.Chars) return;

            SerialPort port = (SerialPort)sender;

            int bytesCount = port.BytesToRead;

            //reading all the bytes from port 
            int bufferSize = port.ReadByte();

            SequentialRingBuffer rBuffer = new SequentialRingBuffer(4096, rxBuffer, true);

            //puting the bytes from ports into ring buffer
            rBuffer.Put((byte)bufferSize);

            //ring buffer with two pointers so rxWrite will be pinting towards the poistion in ring buffer where there is last byte writing is done.
            //and if it is  end of circular buffer then should go back to first poistion and start writing there 
            rxWrite=rBuffer.CurrentLength;

            //now the rxRead should read byte from ring buffer one by one so to parse it.
            
            byte[] tempArray = new byte[256];
            tempArray=rBuffer.ToArray();
        }
    }
}

推荐答案

我仍然认为没有必要这里有一个环形缓冲区。



但是,如果你想使用一个,它必须在类级别定义,而不是在每次事件后超出范围的接收处理程序中定义。 />


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

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

However, if you want to use one, it must be defined at class level and not within your receive handler where it goes out of scope after each event.

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.


Quote:

没有默认值在C#

中实现循环/环形缓冲区你觉得队列类 [ ^ ]是?

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

引用:

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



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

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 ...


您已经在使用循环缓冲区从串口读取数据 [ ^ ],并收到了回答。请不要重新发布。
You already posted this at Using circular buffer for reading data from serial port[^], and received an answer. Please do not repost.


这篇关于如何将数据从串口数据保存到环形缓冲区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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