Ошибки данных в моем методе последовательного приема

1

Я беру данные из серийного инструмента для построения графика на диаграмме. Поток данных составляет 230 кбит/с, а последовательный конвейер заполнен менее чем на 50%, данные поступают примерно на 100 кбит/с и фактически не меняются на самом деле, а скорость и количество.

Используя только программу последовательного терминала, такую как Teraterm, на том же компьютере; Я могу захватить данные и доказать, что как источник данных, так и метод приема теста хороши, и я не вижу ошибок для захваченных данных.

Приложение Windows Forms, которое я разрабатываю, теряет данные. Я уменьшил его от приема, захвата (параллельно), разбора и построения, только для получения и захвата. И обнаружили, что я все еще вижу потерянные данные в захвате.

Я не очень опытный человек Windows, поэтому, возможно, не знаю, как лучше выполнять одни и те же функции. Вот действия, которые я предпринимаю для выполнения действий:

Я использую класс System.IO.Ports.SerialPort. Я изменяю событие.DataReceived через:

+= new SerialDataReceivedEventHandler(comPort_DataReceive);

Затем я вызываю метод open().

Примечание. Возможно, я что-то делаю неправильно, я никогда не очищаю событие.DataReceived с a = = в любой момент, вместо этого каждый раз, когда я открываю, событие добавляется еще раз. Тем не менее, эти проблемы возникают, даже когда я только разговаривал с портом один раз.

Здесь мой код для функции приема данных. RxString - это строка.

    private void comPort_DataReceive(object sender, SerialDataReceivedEventArgs e)
    {
        RxString = comPort.ReadExisting();
        this.Invoke(new EventHandler(ParseData));
    }

    private void ParseData(object sender, EventArgs e)
    {
        // Save to capture file, if capture is enabled
        if ((WriteToFileEnabled == true) && (WriteToFileName != null))
        {
            writeFileHandle.Write(RxString);
        }
        return;
        // Previously would parse and plot data
    }

Итак, как люди могли бы получить получение в этой ситуации, чтобы получить эти данные, не потеряв их?

Следуйте по следующим вопросам: насколько большой буфер для последовательного получения, или мне нужно беспокоиться об этом, если у меня есть разумно реагирующее приложение? Управление потоком не имеет значения, удаленное устройство собирается отправлять данные независимо от того, что было бы, поэтому мой компьютер мог бы взять эти данные и обработать их или проигнорировать. Но как я могу узнать, потерял ли я данные или испытал ошибки фреймов и прочее? Извините. Я прошу, чтобы последний не искал много в структуре класса SerialPort.

  • 0
    Как вы уверены, что данные теряются? Есть ли какая-то закономерность в потере данных?
  • 0
    230 кбит / с - это довольно быстро для последовательного порта ... если вы находитесь в электрически шумной среде или используете ненадежные кабели, вы можете легко столкнуться с повреждением данных. Если отправляющее устройство позволяет, попробуйте уменьшить скорость до 9600 бод и убедиться, что все работает, прежде чем увеличивать скорость. Ошибки четности вызовут исключение. Если вы не используете четность в своем протоколе и не используете рукопожатие, то на самом деле нет никакого способа гарантировать, что вы получаете все данные или что вы получаете их правильно.
Показать ещё 4 комментария
Теги:
winforms
serial-port

1 ответ

3
Лучший ответ

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

Кроме того, только одно из событий, поднятых классом SerialPort, может выполняться одновременно. В примере предположим, что обработчик должен запускать три раза, чтобы получить 85 байтов. При обработке первой части два других не могут выполнить. Если при обработке первой части необходимы одно из других событий, PinChanged или ErrorReceived, они также не могут быть выполнены.

Мои первые два опыта с классом SerialPort состояли из 9600 бит/с терминала и 1 Мбит/с Bluetooth-устройства. То, что работало для более медленного, не работало быстрее, но когда я понял, как быстрее работать, медленнее может использовать ту же методологию.

Моя методология:

  1. Перед открытием последовательного порта я запускаю два других фоновых потока, которые выполняются в цикле do. Первый (Receive) считывает все доступные байты из последовательного порта, добавляет их в буфер и сигнализирует второй поток при каждом чтении. Второй (протокол) определяет, поступило ли полное сообщение, выполняет ли какой-либо байт для преобразования строк, обновляет пользовательский интерфейс и т.д. В зависимости от приложения я могу запустить третий поток, который обрабатывает ошибки и изменения контактов. Все эти потоки дросселируются с помощью Threading AutoResetEvent.

  2. У моего обработчика событий DataReceive есть одна строка в нем, Set в AutoResetEvent, который активирует прием.

Пример VB этого можно найти здесь. Методика SerialPort. С момента принятия этой методологии у меня не было проблем, которые, похоже, угрожают другим пользователям SerialPort и успешно использовали его со скоростью до 2 Мбит/с.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню