Что может повлиять На Значения, возвращаемые Serialport.Read()

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

  •  02-07-2019
  •  | 
  •  

Вопрос

Я написал простое приложение на C # 2.0, используя класс Serialport .Net Framework 2.0 для связи с платой контроллера через COM1.

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

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

Итак, что может повлиять на значения байтов, возвращаемые методом Read ?

Большинство настроек между двумя приложениями идентичны.

Вот список строк, которые отличались в журнале Portmon :

Приложение Delphi :

УСПЕХ IOCTL_SERIAL_SET_CHAR Serial0 EOF: постоянный ток ОШИБКА: 0 BRK:0 EVT:0 Начало:11 НАЧАЛО:13
IOCTL_SERIAL_SET_HANDFLOW Serial0 УСПЕШНОЕ изменение: 0 Замена: 0 XonLimit:256 XoffLimit:256 IOCTL_SERIAL_SET_TIMEOUTS Сериал0 RI УСПЕХА:-1 RM:100 RC:1000 WM: 100 WC: 1000 Маска УСПЕХА IOCTL_SERIAL_SET_WAIT_MASK Serial0:RXCHAR RXFLAG TXПУСТОЙ CTS DSR RLSD КОЛЬЦО ОШИБКИ BRK RX80ПОЛНЫЙ

Приложение на C # :

УСПЕХ IOCTL_SERIAL_SET_CHAR Serial0 EOF:1a ОШИБКА: 0 BRK:0 EVT: 1a XON: 11 XOFF: 13 IOCTL_SERIAL_SET_HANDFLOW Serial0 УСПЕШНОЕ изменение: 0 Замена: 0 XonLimit: 1024 XoffLimit:1024 IOCTL_SERIAL_SET_TIMEOUTS Сериал0 RI УСПЕХА:-1 RM:-1 RC:1000 WM:0 WC: 1000 Маска УСПЕХА IOCTL_SERIAL_SET_WAIT_MASK Serial0:RXCHAR RXFLAG CTS DSR RLSD BRK ОШИБКА КОЛЬЦО

Обновить:

Правильными возвращенными байтами были :91, 1, 1, 3, 48, 48, 50, 69, 66, 51, 70, 55, 52, 93 (14 байты).Последнее значение является простой контрольной суммой.

Были возвращены неправильные значения :91, 241, 254, 252, 242, 146, 42, 201, 51, 70, 55, 52, 93 (13 байты).

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

Событие ErrorReceived указывает на то, что произошла ошибка кадрирования, которая может объяснить неправильные значения.Но вопрос в том, почему SerialPort сталкивается с ошибкой кадрирования, когда приложение Delphi, по - видимому, этого не делает?

Это было полезно?

Решение

Что ж, похоже, проблема решена (по крайней мере, на данный момент).

По-видимому, ошибка кадрирования привела к возврату неверных значений.Я написал приложение VB6, используя элемент управления MSComm, который работал нормально, и сравнил файлы журналов, сгенерированные Portmon.

Я заметил следующие отличия

Приложение VB6 :

IOCTL_SERIAL_SET_HANDFLOW Сериал0 УСПЕХ Встряхивание: 1 Заменить: 0 XonLimit: 256 XoffLimit: 256

Приложение на C # :

IOCTL_SERIAL_SET_HANDFLOW Сериал0 УСПЕХ Встряхивание: 0 Заменить: 0 XonLimit: 1024 XoffLimit: 1024

Поиграв с настройками, я обнаружил, что если я установлю _serialPort.DtrEnable = true приложение C # генерирует следующую запись в журнале :

IOCTL_SERIAL_SET_HANDFLOW Сериал0 УСПЕХ Встряхивание: 1 Заменить: 0 XonLimit: 1024 XoffLimit: 1024

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

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

Вы проверили настройки количества битов данных, стоп-битов и четности?

Бит четности - это своего рода механизм обнаружения ошибок.Например:Если вы отправляете, используя 7 битов данных и один бит четности, восьмой бит будет использоваться для обнаружения ошибок инверсии битов.Если получатель ожидает 8 битов данных и никаких битов четности, результат будет искажен.

К сожалению, вы не упомянули точно, какой тип различий вы получаете.Это случайный символ , который отличается или все ваши входящие данные искажены ?Обратите внимание, что символы, считываемые с помощью функции SerialPort.Read, могут быть изменены системой из-за настройки SerialPort.Кодировка собственность.Этот параметр влияет на интерпретацию входящего текста, поскольку это был текст в ASCII, Unicode, UTF8 или любой другой схеме кодирования, используемой Windows для преобразования "необработанных байтов" в "читаемый текст".

Если вы считываете данные в массив байтов (например:SerialPort.Read) вы должны получить именно те байты, которые вы видите в PortMon.

Если вы преобразуете в символы (SerialPort.ReadLine или SerialPort.readChar), то данные будут закодированы с использованием текущей кодировки (свойство SerialPort.Encoding), что объясняет различия, которые вы видите.

Если вы хотите видеть символы с теми же двоичными значениями, что и байты в проводе, хорошей кодировкой для использования является Latin-1, как описано в этот пост.

Пример:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top