Перейти к содержанию
    

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день,

если вы ловите запрос+ответ и если не принципиально ловить паузы между ними, то разделить запрос и ответ, как мне кажется, можно "расшифровкой" протокола, если конечно данные приняты без ошибок.

При этом методе если запрос принят с ошибкой, то не сможем определить его длину, как следствие не "расшифруем" и ответ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно принимать байты по одному с таймаутом, т.е. таймаут только на приём одного байта. Пока синхронизация приёма пакетов не нарушилась работаем только с crc, если нарушилась, то устанавливаем таймаут равный времени приёма одного байта + небольшой запас (не помню интервал тишины в modbus, вроде три байта). Если передача идёт по стандарту modbus, то таймаут на два-три байта тишины должен помочь

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Эксперименты с таймаутом особо не помогают. При скорости 115200 время передачи байта составляет 95мкс, а таймауты устанавливаются в миллисекундах.

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

Отсюда и лезут проблемы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

т.е. вы подключаетесь к какой либо паре устройств работающих по modbus (запросы отправляете не вы) и задача стоит разобрать протокол (синхронизироваться)?

если да, то можно со сдвигом принятых данных считать crc и где crc верна, там и есть начало пакета. Определить "запрос" или "ответ" можно уже по протоколу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

честно говоря я бы такую задачу решал иначе. А именно - сниффер пишется на МК, и отдает пакеты в комп приплюсовывая к ним time stamp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Отсюда и лезут проблемы.

Вы все правильно понимаете.

Вывод из этого простой : стандартные ОС со стандартными компортами (обычно 16550-compatible) ловить таймауты modbus-rtu неспособны. Ставьте конвертор на МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень давно, чем то подобным занимался (отлавливал пакет modbus который завешивал устройство), сейчас для измерения времянок воспользовался бы каким нибудь цифровым логическим анализатором (например недорогим китайским), а тогда использовал программу COM Port Toolkit (раньше была бесплатной для русcкоговорящих), в ней даже штамп времени есть (вроде как миллисекунды, но с какой точность не знаю). Т.к. по стандарту modbus рекомендуют на скоростях более 19200 делать T3.5 = 1,750мс то возможно программа поймает начало ответа и отправку нового запроса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если пишете сами, попробуйте использовать таймауты драйвера

см. тут

Писать надо на достаточно низком, в хорошем смысле, уровне. С, CPP PAS, с событиями-потоками.

Win32API, ReadFileEx() etc.

Для модбаса надо отлавливать паузы 3.5 байта.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем доброго дня. Есть сеть устройств, работающих по протоколу модбас через RS485.

...

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

как вариант, соберите данные любым готовым сниффером и скормите этой программе

mb_dump_parser

 

если результат устроит и вам нужно в реалтайме, то тогда вердикт "ЭТО ВОЗМОЖНО и без таймаутов, пишите софт"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На тему конвертора мысли были. Но только на самый крайний случай.

Сейчас пока используется модифицированный модбас, в котором есть признаки, позволяющие однозначно определять начало и конец посылок.

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

Сегодня перечитывал старую информацию, которую использовал при освоении программирования ком порта и нашёл то, что пропустил. Есть в структуре DCB символ XOFCHAR, который позволяет определить конец посылки. Осталось непонятным, его записывает драйвер в массив приёма или этот символ должен быть записан передатчиком в конец сообщения.

Интернет по этому поводу подробностей пока не дал. Буду пробовать экспериментально.

Была ещё мысль отслеживать событие DCD data carrier detect, но боюсь оно ожидаемого результата не даст.

Была мысль алгоритмически ловить конец посылки через подсчёт CRC, но вариант не самый красивый. Хотя должен привести к результату.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

честно говоря я бы такую задачу решал иначе. А именно - сниффер пишется на МК, и отдает пакеты в комп приплюсовывая к ним time stamp

Я бы тоже решал по-другому. А именно: с открытия MSDN и прочтения всего, что касается работы с COM-портом. Чего автор как видно не сделал.

Иначе он знал бы о функции SetCommTimeouts() WinAPI и многих других полезных. А не строил пустые предположения.

Далее: установил-бы ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD

как советует MSDN, повысил приоритет принимающего потока, а также прочитал в MSDN про семейство функций QueryPerformanceFrequency()/QueryPerformanceCounter() и понял бы, что даже 95мкс - не есть проблема.

Другое дело что всё это лучше делать на железном RS-232 компа, а не USB-COM переходнике, времянки которого сомнительны.

 

Даже и с железным COM-портом и приоритетом потока ==REALTIME возможно будут проблемы из-за работы других драйверов винды (винта, видео и т.п.). Так что возможно лучше вынести такую работу на уровень драйверов.

 

Есть в структуре DCB символ XOFCHAR, который позволяет определить конец посылки.

Это вообще из другой оперы. Это для software flowcontrol.

 

Была мысль алгоритмически ловить конец посылки через подсчёт CRC, но вариант не самый красивый. Хотя должен привести к результату.

Лучше откройте наконец-то MSDN, а не занимайтесь ерундой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

QueryPerformanceFrequency()/QueryPerformanceCounter() и понял бы, что даже 95мкс - не есть проблема.

К чему опрос счетчиков хоть с тактовой процессора, если их НЕЛЬЗЯ со сколь-нибудь детерминированной точностью привязать к событиям UART.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читал я MSDN в своё время, когда осваивал программирование ком порта. Но это ни чего не даёт. Когда драйвер захочет вернуть данные пользовательской программе, тогда и вернёт. И совсем не в режиме реального времени.

А с таймоутами я экспериментировал, результат далёк от желаемого.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

К чему опрос счетчиков хоть с тактовой процессора, если их НЕЛЬЗЯ со сколь-нибудь детерминированной точностью привязать к событиям UART.

ТСу нужно не опрашивать счётчики, а вести лог обмена по каналу UART. Причём с таймштампами точностью до десятков мкс. Ну или хотя-бы видеть, что между двумя соседними байтами X1 и X2 была хоть какая-то пауза, обнаруженная драйвером канала или её не было. Аппаратура UART 16550 позволяет определять наличие паузы, значит и драйвер это должен видеть. А функция SetCommTimeouts(), как следует из её описания, должна позволить получить эту инфу юзеру.

 

Читал я MSDN в своё время, когда осваивал программирование ком порта. Но это ни чего не даёт. Когда драйвер захочет вернуть данные пользовательской программе, тогда и вернёт. И совсем не в режиме реального времени.

Т.е. - Вы утверждаете что MSDN врёт, говоря, что:

If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:
If there are any bytes in the input buffer, ReadFile returns immediately with the bytes in the buffer. 
If there are no bytes in the input buffer, ReadFile waits until a byte arrives and then returns immediately.

Читаем первую строку с "if" и вторую, видим там слово "immediately", думаем.

Я почти уверен, что если приоритет вызывающего потока будет ==THREAD_PRIORITY_TIME_CRITICAL, а приоритет процесса ==REALTIME_PRIORITY_CLASS, то как только аппаратура UART зафиксирует, что в FIFO есть символы и с момента приёма последнего из них прошло более 3.5 символьных интервала, так сразу и вернёт управление вызывающему потоку.

Возможно даже хватит меньших приоритетов у процесса/потока, главное - превысить приоритеты всех других работающих в системе потоков.

И всё конечно зависит ещё от драйвера. Стандартный виндовый драйвер для UART 16550 на сис. шине должен соответствовать требованиям MSDN. Про сторонние драйвера UART, тем более для USB-UART речи нет - они могут только примерно соответствовать MSDN. Но думаю, если устройство, реализующее CDC-класс USB, при отправке данных, выделяет разные кадры ModBus в отдельные пакеты по USB, то и драйвер CDC-класса под виндой также сможет выполнить требования SetCommTimeouts().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...