Требуется справка по последовательному порту .NET, в первую очередь для данных, полученных в нескольких “пакетах”

StackOverflow https://stackoverflow.com/questions/891475

  •  23-08-2019
  •  | 
  •  

Вопрос

Я очень новичок в отправке данных через последовательный порт .net и я заметил после внедрения аналога TCP, что с serial мне было бы не так просто сделать это!

Итак, чтобы начать с самого начала, я почти достиг своей реализации последовательной двунаправленной связи, я просто застрял на нескольких вещах:-

  1. Мои чтения распределяются по нескольким сообщениям или принимаются в виде фрагментированного ответа через COM-порт, и я не знаю, какие настройки мне могут понадобиться или как мне следует написать код по-другому, чтобы исправить это.Что могло бы стать причиной этого?Я проверяю сообщение в точке останова на SerialPort_DataReceived.

В основном данные должны быть отправлены в виде:

01: LS|DA090521|TI111043|q
02: PS|RN102|PTC|TA1040000|P#0|DA090521|TI111429|j

но он разделяется (в случайных позициях при каждом запрошенном чтении)

01: LS|DA090521|TI111
02: 043|q
03: PS|RN102|PTC|TA1
04: 0000|P#0|DA090521|TI111429|j

- Ответ на вопрос 1 получен, спасибо Крису У.и другие!Теперь у меня есть сообщение, которое, как я ожидаю, будет постепенно собираться из фрагментов (обращая внимание на STX, {msg body}, ETX), а затем действие, выполняемое, когда сообщение будет полностью собрано, и я очень доволен, что оно отправлено в потокобезопасную очередь.

.2.Я получаю символ "|" во время чтения почти в каждом цикле, связано ли это с командой, которую я каким-то образом неправильно установил, артефактом последовательной связи или чем-то еще, что устройство отправляет мне?(Однако я так не думаю, поскольку гипертерминальное подключение показывает, что этот символ не отправляется непрерывно.)

.3.Можете ли вы подтвердить, что я правильно считываю и записываю данные соответствующими методами?

Спасибо, ребята, что тоже обратили внимание на два других моих вопроса.

Соответствующий код выглядит следующим образом:

...
    //                          COM3,    9600,     None,   8,        One
    SerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits);
    if (SerialPort.IsOpen) SerialPort.Close();
    // SerialPort.RtsEnable = true; // Request-to-send
    // SerialPort.DtrEnable = true; // Data-terminal-ready
    SerialPort.ReadTimeout = 150; // tried this, but didn't help
    SerialPort.WriteTimeout = 150; // tried this, but didn't help
    SerialPort.Open();

    SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
}

void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // Process received data
    SerialPort sp = (SerialPort)sender;
    byte[] buffer = new byte[sp.BytesToRead];
    int bytesRead = sp.Read(buffer, 0, buffer.Length);

    // message has successfully been received
    message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
}

public bool SendMessage(string text)
{
    // Only send message if a client is connected
    if (SerialPort != null && SerialPort.IsOpen)
    {
        byte[] buffer = Encoding.ASCII.GetBytes(text);
        SerialPort.Write(buffer, 0, buffer.Length);
    }
}
Это было полезно?

Решение

Мои чтения распределяются по нескольким сообщениям

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

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

Я получаю символ "|" во время чтения почти в каждом цикле

Каково шестнадцатеричное значение этого символа?Посмотрите, является ли установка Handshake собственность на XOnXOff или RequestToSendXOnXOff улучшает ситуацию.

Другие советы

На более низком уровне последовательный порт может решить, когда инициировать событие приема данных.Возможно, он решит сделать это до того, как прибудет "полный" пакет.Но, похоже, у вас есть символ терминатора в вашем ожидаемом наборе данных.Если это так, вы можете сделать следующее (обратите внимание, что я изменил ваше назначение SerialPort, чтобы избежать синтаксической путаницы:

        p = new SerialPort(PortName, BaudRate, Prty, DataBits, SBits);
        p.NewLine = Terminator;

где Terminator - это строка, содержащая ваш символ (ы) завершения.Затем вы можете использовать SerialPort.ReadLine() (и SerialPort.WriteLine(), если это применимо).Это могло бы, по крайней мере, помочь с вашей первой проблемой.

Я много занимался программированием последовательных портов Win32, но совсем немного с .NET, так что отнеситесь к моему совету со всей серьезностью.

Мои чтения распределяются по нескольким сообщениям или принимаются в виде фрагментированного ответа через COM-порт, и я не знаю, какие настройки мне могут понадобиться или как мне следует написать код по-другому, чтобы исправить это.

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

Если вы хотите получить больше данных, вы можете попробовать следующее:

  • настройка свойства System.Int32 ReceivedBytesThreshold
  • использование синхронного ввода-вывода и указание фиксированного количества байтов для чтения, а не приема на основе событий

Я получаю символ "|" при чтении почти в каждом цикле, это это из-за команды, которую я установил каким-то образом неправильно, артефакт последовательной связи или что-то еще, что устройство отправляет мне?(Я так не думаю хотя, поскольку гипертерминальное подключение показывает, что этот символ не передается непрерывно.)

Если вам интересно, что происходит за чертой, ознакомьтесь ПортМон из SysInternals, бесплатное приложение, которое будет отслеживать ваш com-порт во время передачи данных по линии.Это кажется техническим, но на самом деле вам просто нужно посмотреть на команды IRP_MJ_WRITE и IRP_MJ_READ, и в строке вы увидите длину в байтах и данные, отправленные по проводу.С помощью этого вы должны быть в состоянии определить, связана ли проблема с объектом .NET SerialPort или устройство действительно отправляет "|" по строке.

Можете ли вы подтвердить, что я правильно считываю и записываю данные в соответствующие методы.

Это выглядит подходящим для метода получения данных, основанного на событиях.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top