Serial, RS422, In C #, событие TxDone не запускается, данные не принимаются - PullRequest
3 голосов
/ 10 февраля 2011

Я пишу приложение, которое использует 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 (или любые другие процедуры проверки строки). Кроме того, закрытие и повторное открытие порта не только не решает эту проблему, но и перезагрузка программного обеспечения, когда устройство все еще работает, также ничего не делает. Только аппаратная перезагрузка. </p>

Событие My 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.

Мысли? Аппаратное или программное обеспечение связано, я проверяю все, что могу проверить.

Ответы [ 2 ]

1 голос
/ 10 февраля 2011

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

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

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

0 голосов
/ 19 апреля 2011

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

...