Что может повлиять на значения, возвращаемые Serialport.Read () - PullRequest
4 голосов
/ 23 сентября 2008

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

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

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

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

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

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

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

IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF: dc ERR: 0 BRK: 0 EVT: 0 XON: 11 XOFF: 13
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 0 Заменить: 0 XonLimit: 256 XoffLimit: 256 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI: -1 RM: 100 RC: 1000 WM: 100 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Маска: RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR RING RX80FULL

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

IOCTL_SERIAL_SET_CHAR Serial0 SUCCESS EOF: 1a ERR: 0 BRK: 0 EVT: 1a XON: 11 XOFF: 13 IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCCESS Shake: 0 Заменить: 0 XonLimit: 1024 XoffLimit: 1024 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI: -1 RM: -1 RC: 1000 WM: 0 WC: 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Маска: RXCHAR RXFLAG CTS DSR RLSD BRK ERR RING

UPDATE:

Правильные возвращенные байты были: 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, по-видимому, этого не делает?

Ответы [ 4 ]

2 голосов
/ 08 октября 2008

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

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

Я подобрал следующие отличия

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

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

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

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

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

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

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

0 голосов
/ 23 сентября 2008

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

0 голосов
/ 23 сентября 2008

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

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

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

Пример:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")
0 голосов
/ 23 сентября 2008

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

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

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