Nishikant Tayade Ответов: 3

Как сохранить данные из последовательного порта в кольцевой буфер?


Я разрабатываю настольное приложение для связи через последовательный порт.Аппаратное обеспечение, подключенное к последовательному порту, отправляет данные в пакете.

Но количество байтов в этом пакете неизвестно,поэтому используется кольцевой буфер.

в C#нет стандартной реализации циклического/кольцевого буфера,поэтому я использую один из них, предоставленный на GitHub https://github.com/xorxornop/RingBuffer/blob/master/PartiallyConcurrent/RingBuffer.cs

Я хочу сохранить данные в кольцевом буфере как полученные,а затем проанализировать их(например,проверить наличие байтов заголовка, идентификатора устройства, байта состояния и т. д.), И если их там нет, то отбросить их.

Я пробовал различные реализации, но не смог получить правильную реализацию.

Что я уже пробовал:

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();
        }
    }
}

3 Ответов

Рейтинг:
24

Jochen Arndt

Я все еще не думаю, что здесь есть необходимость в кольцевом буфере.

Однако если вы хотите использовать один из них, он должен быть определен на уровне класса, а не в вашем обработчике приема, где он выходит из области действия после каждого события.

У вас уже есть буфер: rxBuffer Чтобы сделать это кольцевым буфером, все, что вам нужно сделать, - это обработать доступ на запись с помощью rxOffset соответственно:

// 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 не будет переполнять эту позицию чтения).

Но, реализуя вышеизложенное, вы можете признать, что это не решает вашу проблему. На самом деле ваша проблема заключается не в том, как реализовать кольцевой буфер, а в том, чтобы определить, как полученные данные должны обрабатываться (обрабатываться). Это задача, которую необходимо выполнить перед написанием любой строки кода. Как только вы определили это, вы можете подумать о возможных реализациях.


Рейтинг:
1

OriginalGriff

Цитата:
нет реализации по умолчанию кольцевой буфер/кольцо с#
А как вы думаете, что это такое? Класс Очереди[^] есть?
Цитата:
Этот класс реализует очередь в виде кругового массива. Объекты, хранящиеся в очереди, вставляются с одного конца и удаляются с другого.

Очереди и стеки полезны, когда вам нужно временное хранилище для информации; то есть, когда вы можете отказаться от элемента после получения его значения. Используйте Queue, если вам нужно получить доступ к информации в том же порядке, в котором она хранится в коллекции ...


Richard MacCutchan

Репост, и вы дали тот же ответ раньше.

OriginalGriff

Разве copy'n'paste не великолепен?
Я заметил репост после того, как опубликовал это, но потом забыл удалить "новую" версию ... Мне нужно еще кофе ...
Я избавлюсь от него прямо сейчас.

Рейтинг:
0

Richard MacCutchan

Вы уже разместили это на сайте Использование кольцевого буфера для считывания данных из последовательного порта[^], и получил ответ. Пожалуйста, не делайте репостов.


Richard Deeming

Вы делать знаете, вы можете использовать маленький красный флажок в правом нижнем углу вопроса, чтобы сообщить о нем как о репосте, не так ли? :)

(Мой доклад был первым.)

Richard MacCutchan

Да, конечно, но, будучи "в определенном возрасте", я иногда забываю вещи. :(

Richard Deeming

Был там, получил футболку. Если бы я только мог вспомнить, куда я его положил! :)