Требуется помощь последовательного порта .NET, прежде всего с данными, полученными в виде нескольких «пакетов» - PullRequest
2 голосов
/ 21 мая 2009

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

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

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

Ответы [ 3 ]

4 голосов
/ 21 мая 2009

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

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

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

Я получаю "|" Символ через мой прочитал почти каждый цикл

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

3 голосов
/ 21 мая 2009

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

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

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

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

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

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

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

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

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

3 голосов
/ 21 мая 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...