Последовательный, RS422, в C #, событие TxDone не запускается, данные не принимаются

Я пишу приложение, использующее OpenNETCF.IO.Serial (открытый исходный код, см. серийный код здесь) для его последовательной связи на устройстве Windows CE 6.0. Это приложение написано на C # в Compact Framework 2.0. Я не верю, что проблема, которую я собираюсь описать, конкретно связана с этими деталями, но может оказаться, что я ошибаюсь в этом отношении.

Проблема, с которой я сталкиваюсь, заключается в том, что по-видимому случайным образом (читается как: прерывистая проблема, которую я пока не могу надежно воспроизвести) данные не могут быть переданы или получены до тех пор, пока само устройство не будет перезагружено. Устройство Windows CE взаимодействует с системой, в которой запущено совершенно другое приложение. Перезагрузка этой другой системы и отключение / повторное подключение кабелей связи, похоже, не решает эту проблему, а только перезагрузка устройства Windows CE.

Единственным признаком возникновения этой проблемы является отсутствие события TxDone от запуска OpenNETCF (ищите «TxDone ();» в классе OpenNETCF.IO.Serial) и отсутствие данных, когда я точно знаю, что подключенный система отправляет данные.

Любое символьное значение от 1 до 255 (0x01 - 0xFF) может быть отправлено и получено в нашей последовательной связи. Нулевые значения отбрасываются.

Мои настройки последовательного порта: 38400 бод, 8 бит данных, без контроля четности, 1 стоповый бит (38400, 8n1). Я установил размер входного и выходного буфера равным 256 байтам. Событие DataReceived происходит всякий раз, когда мы получаем 1 или более символов, а передача происходит, когда в выходном буфере 1 или более байтов, поскольку сообщения имеют переменную длину.

Рукопожатие не используется. Поскольку это RS422, используются только 4 сигнала: RX +, RX-, TX +, TX-.

Я получаю событие «DataReceived», я читаю все данные из входного буфера и создаю свой собственный буфер в своем коде, чтобы проанализировать его на досуге вне события DataReceived. Когда я получаю командное сообщение, я отправляю быстрое сообщение с подтверждением. Когда другая система получает командное сообщение от устройства Windows CE, она отправляет обратно сообщение быстрого подтверждения. Сообщения с подтверждением не получают дальнейших ответов, поскольку они предназначены для простого «Ага, понятно». В моем коде я получаю / передаю через несколько потоков, поэтому я использую ключевое слово lock, чтобы не передавать несколько сообщений одновременно в нескольких потоках. Двойная проверка кода показала, что я не зацикливаюсь на каких-либо блокировках.

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

Любые идеи, варианты для проверки, предложения, идеи и т. Д. Приветствуются. Это то, с чем я боролся самостоятельно в течение нескольких месяцев, я надеюсь, что ответы или комментарии, которые я получаю здесь, могут помочь в решении этой проблемы. Заранее спасибо.

Редактировать, 24.02.2011:
(1) Я могу воссоздать только ошибку при загрузке системы, с которой обменивается данными устройство Windows CE, а не при каждой загрузке. Я также посмотрел на сигналы, синфазное напряжение колеблется, но амплитуда шума, возникающего при загрузке системы, кажется, не связана с тем, возникает проблема или нет, я видел, что размах напряжения 25 В не вызывает проблем, когда пик 5 В -тогда проблема возникла снова).
Проблема продолжает звучать, все больше и больше связана с оборудованием, но я пытаюсь выяснить, что может вызвать симптомы, которые я вижу, поскольку ни одно из оборудования на самом деле не выходит из строя или не выключается , по крайней мере, там, где я смог измерить сигналы. Приношу свои извинения, но я не могу назвать артикулы компонентов оборудования, поэтому, пожалуйста, не спрашивайте, какие компоненты используются.

(2) В соответствии с предложением @ctacke, я обеспечил, чтобы все передачи проходили через одно и то же место для удобства обслуживания, безопасность потоков, которую я ввел, по существу выглядит следующим образом:

lock(transmitLockObj)
{
    try
    {
        comPort.Output = data;
    }
    [various catches and error handling for each]
}

(3) Получение ошибок UART OVERRUN в тесте, где отправлялись и принимались ‹10 байтов с интервалом времени около 300 мсек на скорости 38400 бод. Как только он получает ошибку, он переходит к следующей итерации цикла, НЕ запускает ReadFile и НЕ запускает событие TxDone (или любые другие процедуры проверки строк). Кроме того, не только закрытие и повторное открытие порта ничего не делает для решения этой проблемы, но и перезагрузка программного обеспечения при работающем устройстве тоже ничего не дает. Только аппаратная перезагрузка.

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

try
{
    byte[] input = comPort.Input; //set so Input gets FULL RX buffer

    lock(bufferLockObj)
    {
        for (int i = 0; i < input.Length; i++)
        {
            _rxRawBuffer.Enqueue(input[i]);
            //timer regularly checks this buffer and parses data elsewhere
            //there, it is "lock(bufferLockObj){dataByte = _rxRawBuffer.Dequeue();}"
            //so wait is kept short in DataReceived, while remaining safe
        }
    }
}
catch (Exception exc)
{
    //[exception logging and handling]
    //hasn't gotten here, so no point in showing
}

Однако сразу после истечения времени ожидания вызова WriteFile в первый раз в тесте я начал получать ошибки UART OVERRUN. Я честно не вижу, как мой код вызывает состояние UART OVERRUN.

Мысли? Что касается оборудования или программного обеспечения, я проверяю все, что могу.


person Peter Lacerenza    schedule 10.02.2011    source источник
comment
В прошлом у меня были аналогичные проблемы на полной платформе .NET (Windows XP) - в итоге я добавил хак, который закрывал и снова открывал последовательный порт в случае остановки данных; не идеален для долгосрочного решения. Я не уверен, что закрытие / повторное открытие вернет его в онлайн для вас.   -  person Justin    schedule 10.02.2011
comment
У вас маленькие буферы, высокая скорость передачи данных. Кр * п бывает.   -  person Hans Passant    schedule 10.02.2011
comment
@Hans, сообщения имеют переменную длину, но наибольшее возможное сообщение, которое я рассчитал, составляет ~ 50 байт, и это редкое явление. Когда событие DataReceived правильно запускается каждый раз, когда последовательная библиотека проверяет, есть ли в буфере 1 или более байтов, 256 теоретически оказывается приличным размером. Я также пытался изменить размер буферов при тестировании, чтобы убедиться, что практический опыт соответствует теории, размеры буфера ничего не решают. К сожалению, ничего не могу поделать со скоростью при тестировании.   -  person Peter Lacerenza    schedule 10.02.2011
comment
@Justin, протестировал закрытие / повторное открытие (с произвольным, чрезмерным 2-секундным временем ожидания между закрытием и повторным открытием) на ранних этапах устранения неполадок. Связь восстановится однажды в синюю луну, если что. Он нигде не восстановился надежно, и я не знаю, было ли это просто удачей розыгрыша, который он восстановил в обстоятельствах, которые он сделал при закрытии / повторном открытии. Тем не менее, спасибо за совет, я согласен с тем, что это решение, которое следует попробовать, когда у кого-то есть такая проблема.   -  person Peter Lacerenza    schedule 10.02.2011
comment
Можете ли вы воспроизвести проблему, вызвав функции последовательного порта WinAPI ?   -  person Ben Voigt    schedule 24.02.2011
comment
@Ben, Последовательная библиотека OpenNETCF работает через p / вызов функций последовательного порта WinAPI, то есть ReadFile, WriteFile, ClearCommError, WaitCommEvent и т. Д. Так что, технически говоря, ответ положительный? Я уже работаю над p / вызовом функций последовательного порта WinAPI, так получилось, что это выполняется последовательной библиотекой, написанной другой библиотекой с открытым исходным кодом (опять же, ссылка для загрузки на исходный исходный код находится в верхней части мой первоначальный вопрос).   -  person Peter Lacerenza    schedule 24.02.2011


Ответы (2)


Все звучит правильно, но ваши наблюдения вроде как показывают, что это не так.

Поскольку вы заявили, что отправляете из нескольких потоков, первое, что я сделал бы, это внедрил какой-то механизм для отправки, при котором все запросы на отправку поступают в одно место перед вызовом экземпляра последовательного объекта. Конечно, вы говорите, что обеспечили безопасность потоков, но сериализация этих вызовов через одно место поможет укрепить это (и сделать код более удобным в обслуживании / расширяемым).

Затем я, вероятно, добавил бы некоторую временную обработку в Serial lib, чтобы специально установить событие или прерывание в отладчике, когда вы выполнили Tx, но событие TxDone не срабатывает в течение некоторого ограничивающего периода. Всегда возможно, что в Serial lib есть ошибка (поверьте мне, автор этого кода далеко не безошибочен), когда какое-то состояние гонки проходит.

person ctacke    schedule 10.02.2011
comment
Следил за вашей передачей из того же места в предложении кода, без изменений в производительности, но я согласен с точкой поддержки. В последовательной библиотеке добавлено событие для (1) прямо перед вызовом ReadFile, (2) сразу после вызова ReadFile, когда он завершил это, при подозрении на тайм-аут ReadFile и (3) в другом случае if (... ) {DataReceived event} на всякий случай. Я закончил тем, что зарегистрировал ошибки UART OVERRUN, где он больше не запускает ReadFile. Всегда. Событие DataReceived только помещает байты в очередь и уходит, и в этом тесте мы говорим о 10 байтах каждые 300 мс на скорости 38400 бод. - person Peter Lacerenza; 24.02.2011

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

person Peter Lacerenza    schedule 19.04.2011