|
Modbus RTU подобный протокол, проблема реализации, Может есть готовый с описанием. |
|
|
|
Jul 30 2007, 18:44
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(singlskv @ Jul 30 2007, 21:01)  Miltimedia Timers намного лучше чем Sleep, по крайней мере они, насколько я помню, не дают при задержке например 3мс, задержку 150мкс  Правда точность мультимедейных таймеров тоже не "блестящая", примерно 1-3 мс. Так что если нужен полный контроль - PerformanceCounters, в остальных случаях мультимедиа таймеры, а Sleep это только на на случай если нашему процессу действительно нужно поспать по крайней мере 20 мс (максимальное время такта операционки которое я лично встречал) Совершенно с Вами согласен. Подписываюсь под всеми пунктами. Sleep я безусловно тоже использую. И потоки и MMTimer. Вариант процедуры его я и привёл. Но у меня поддёргивается чуть чуть. На взгляд синхронно с секундными тиками.  Думаю это тоже можно убрать, да просто нет необходимости пока. Цитата С успехом в своих разработках применяю смешанный протокол.Посылка с начальным и завершающим символом, а передаются байты.Все остальное от RTU .Это более скоростной протокол и проще программый код. Тоже так поступаю, но не называю это modbus. Ну а если делаешь modbus, то будь добр соблюдай весь протокол. Или называй его modbus- подобный протокол. Понятно, что если не можешь физически сделать, то что тут уже попишешь. Поэтому в мастере на PC я тоже отступаю от стандарта. Ну а теперь я вообще не придерживаюсь modbus. Считаю его устаревшим. Мы уже здесь где-то обсуждали эти вопросы. Хочется использовать стандартный, но не перегруженный условностями протокол, взявший лучшее от modbus. Тут обсуждалась "пирамида", "wake" и др. Надо как-нибудь собраться с силами и прочитать-вникнуть. Может я стану горячим поборником.
|
|
|
|
|
Jul 30 2007, 20:15
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Alex ma @ Jul 29 2007, 20:34)  Вся фишка в проблеме определения стартовой последовательности, в Modbus – это пауза 3,5 кадра вроде.... Да, но на PC таймер под Windows только 1 мс дискретность. Ну не знаю как в PC (и надо ли оно вообще делать Modbus slave на PC). На МК я поступаю так: Приняв любой байт по УАРТу взвожу таймер, на интервал равный 4-м кадрам. И продолжаю прием. По прерыванию таймера - взвожу флажек "Таймаут". В этом же обработчике таймера, отцепляю буфер текущего пакета, и подставляю вместо него новый. Цитата(bodja74 @ Jul 30 2007, 14:35)  Делать задержки на таймере не самое лучшее решение,используйте API функцию SLEEP из KERNEL32. Типа так обьявляем RTU-Мастер не обязан выдерживать точные паузы. Если скорость обмена некритична, то и таймером можно пользоваться, и Sleep'ом, чем угодно ;> Самое плохое это то, что винда может втавлять непредсказуемые паузы внутри пакетов, что слейвом воспринимается однозначно - как куча битых пакетов.
|
|
|
|
|
Jul 30 2007, 20:23
|
Местный
  
Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621

|
Тема получения точных задержек в виндозе очень благодтная и крайне бесполезная. Даже если поднять приоритет потока до 31 все равно на маленьких задержках большой разброс будет. Причина в планировщике. Мелкософты большими красными буквами пишут - ВИНДОУЗ НЕ ОС РЕАЛЬНОГО ВРЕМЕНИ. Главное для МОДБАСА это то, что пауза между пакетами не менее, чем. Теперь по теме. Цитата У ведущего МК два USART один мастер второй слейв, один к PC, второй к другим МК, PC – мастер. Так МК реализует MODBUS? Как переходник между СОМ и MODBUS? А смысл? Мастер легко запустить и на РС, нормально будет работать, если только не понадобится суперскорость более 115200. А если присутствие контроллера-мастера необходимо по определенным соображениям, и все слейвы тоже "свои", то может стоит использовать 9-битный формат? Никаких пауз, все очень четко и никакой головной боли. А это как?: Цитата а между контроллерами меньше Какое такое "между контроллерами"? Это же не крутой PROFIBUS!
|
|
|
|
|
Jul 30 2007, 20:44
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Цитата(singlskv @ Jul 30 2007, 19:27)  Ну если Вы не верите счетчикам ядра, то тады, я Вас вероятно не смогу убедить что приведенные мной значения это правда погуглите по таким функциям: QueryPerformanceFrequency QueryPerformanceCounter Возможно после этого Вы лучше поймете как все устроено у Windows, и поймете как правильно измерять задержки под ней. Ей богу заставляете заниматься херней  погуглил ,нашел ,и толку ? нет конечно действительно погрешность существует,про корорую я в принципе знал ,но из 3мс на 150мкс - вы меня прям испугали  Для чистоты эксперимента я QueryPerformanceCounter liStart и QueryPerformanceCounter liStop вложил вовнутрь цикла. Вот результат. рис1 - задержка 10мс (разброс до 5) рис2 - задержка 3мс (разброс до 1.5) и заметьте разброс практически всегда в большую сторону ,хотя не скрою бывает хоть и редко ,но вменьшую до 10% от заданного значения ,но по крайней мере не в 20 раз меньше  насчет мультимедийных таймеров - это хорошая мысль ,у них приоритет может быть выше ,надо будет почесать репу около них
Эскизы прикрепленных изображений
|
|
|
|
|
Jul 30 2007, 20:47
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
oran-be, когда вы цитируете кого-то, то указывайте автора цитаты. А то непонятно из какого сообщения и чья цитата в вашем сообщении. Если копипастите текст, то для цитирования достаточно в открывающий тэг QUOTE дописать ник автора QUOTE=nickname Пример Цитата(rezident) Это моя цитата
|
|
|
|
|
Jul 30 2007, 21:04
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(bodja74 @ Jul 31 2007, 00:44)  Ей богу заставляете заниматься херней  Давайте не будем иронизировать пока не разобрались в вопросе  Вот Вам код под Visual Studio(под другое сможете отрихтовать ?) Код #include "stdafx.h" #include <windows.h> #include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[]) { LARGE_INTEGER freq,begin,end; __int64 b,e,f,r; int d[]={0,1,2,3,10,16,20}; QueryPerformanceFrequency(&freq); f=(__int64)freq.QuadPart; printf("Freq=%u\n",f); printf("\nSleep results in microseconds\n\n"); printf(" "); for (int i=0;i<sizeof(d)/sizeof(int);i++) { printf("Sleep(%2u) ",d[i]); } printf("\n"); for (int i=0;i<sizeof(d)/sizeof(int);i++) { printf("----------",d[i]); } printf("\n"); for (int j=0;j<20; j++) { for (int i=0;i<sizeof(d)/sizeof(int);i++) { QueryPerformanceCounter(&begin); Sleep(d[i]); QueryPerformanceCounter(&end); b=(__int64)begin.QuadPart; e=(__int64)end.QuadPart; f=(__int64)freq.QuadPart; r=((e-b)*10000000)/f/10; printf("%10u",r); int t=rand(); for (int k=0;k<t;k++) { int tt=rand()/100; for (int kk=0;kk<tt;kk++) rand(); } } printf("\n"); } return 0; } Сразу же скажу, что код написан неоптимально(на коленке в N часов ночи) только для проверки. Да, и еще, для чистоты эксперимента, вырубите все лишнее, например Qip, дело в том что некоторые проги меняют такт операционки (Qip например), то что они так поступают, не есть гуд, но они так поступают....
|
|
|
|
|
Jul 30 2007, 22:45
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(defunct @ Jul 31 2007, 00:15)  Ну не знаю как в PC (и надо ли оно вообще делать Modbus slave на PC). Вам тоже снятся такие сны ? Что Вас "заставили" сделать слейв на PC ? (шучу...) ИМХО, слейв на PC, штука практически нереализуемая... (в рамках стандарта, по крайней мере)
|
|
|
|
|
Jul 31 2007, 04:15
|
Местный
  
Группа: Свой
Сообщений: 252
Регистрация: 14-09-06
Пользователь №: 20 377

|
Цитата(defunct @ Jul 30 2007, 23:15)  На МК я поступаю так: Приняв любой байт по УАРТу взвожу таймер, на интервал равный 4-м кадрам. И продолжаю прием. По прерыванию таймера - взвожу флажек "Таймаут". В этом же обработчике таймера, отцепляю буфер текущего пакета, и подставляю вместо него новый. А как вы сделали, «Приняв любой байт по УАРТу взвожу таймер», в это время по юарту идут байты, таймер тикает, и переполняется, устанавливается флаг переполнения, или вы по приему байта с юарта сбрасываете счетчик таймера?
|
|
|
|
|
Jul 31 2007, 04:49
|
Знающий
   
Группа: Свой
Сообщений: 506
Регистрация: 29-09-05
Из: Донецк
Пользователь №: 9 063

|
Цитата(SasaVitebsk @ Jul 30 2007, 21:44)  Тоже так поступаю, но не называю это modbus. Ну а если делаешь modbus, то будь добр соблюдай весь протокол. Или называй его modbus- подобный протокол. Понятно, что если не можешь физически сделать, то что тут уже попишешь. Поэтому в мастере на PC я тоже отступаю от стандарта. Ну а теперь я вообще не придерживаюсь modbus. Считаю его устаревшим. Мы уже здесь где-то обсуждали эти вопросы. Хочется использовать стандартный, но не перегруженный условностями протокол, взявший лучшее от modbus. Тут обсуждалась "пирамида", "wake" и др. Надо как-нибудь собраться с силами и прочитать-вникнуть. Может я стану горячим поборником.  Ну, там где надо, я протокол не нарушаю Мне тоже не нравится Modbus, но многие фирмы реализуют его в своей продукции и тут ничего не поделаешь.Конечно, если готовишь продукцию для рынка, то надо более четко реализовать протокол. Цитата(_Алекс @ Jul 31 2007, 07:15)  А как вы сделали, «Приняв любой байт по УАРТу взвожу таймер», в это время по юарту идут байты, таймер тикает, и переполняется, устанавливается флаг переполнения, или вы по приему байта с юарта сбрасываете счетчик таймера? Спецификация Modbus RTU предписывает непрерывный поток данных.Поэтому по каждому символу необходимо сбрасывать (устанавливать) таймер настроенный на интервал равный 3,5 символам.Когда символы кончатся , сработает таймер.По срабатыванию таймера можно считать, что пакет пришел. Есть и другие методы приема.
|
|
|
|
|
Jul 31 2007, 04:55
|
Местный
  
Группа: Свой
Сообщений: 234
Регистрация: 30-03-07
Из: Одесса
Пользователь №: 26 621

|
Цитата(rezident) когда вы цитируете кого-то, то указывайте автора цитаты Остается поблагодарить за раскрытие секретов мастерства. Цитата(defunct) Самое плохое это то, что винда может втавлять непредсказуемые паузы внутри пакетов Если пакет достаточно длинный. В современных РС СОМ обычно интегрирован в чипсет и поэтому может отличатся от стандартного. Глубина ФИФО, как я ка то обнаружил экспериментальным путем, не соответствует стандартным 16 байтам, а обычно имеет совершенно левое значение. Чтобы узнать глубину фифо, надо соединить на COM'e RX и TX и сначала записать в него чего-нибудь большое, а потом считать. Считается столько, сколько осталось в ФИФО. Я прпробовал на двум мамках - на одной оказался 91 байт, на другой - 173. Если длина пакета менее длины ФИФО, паузы не будет. А если не привязываться к ФИФО, то минимизировать вероятность появления пауз можно только путе повышения приоритета и соответствующей настройки СОМа. Движок для слейва на МК под РС485 с использованием пауз для определения старта пакета может выглядеть следующим образом: Используется аппаратный таймер и УАРТ. Флаг переполнения таймера используется как признак адреса. При инициализации сбрасывается. Время на таймере устанавливается при инициализации и при приеме любого байта равным требуемый интервал + время приема 1 байта. Обработчик прерывания по УАРТ, после взвода таймера, анализирует флаг переполнения таймера и, если он установлен, то он сбрасывается и происходит анализ принятого значения. Если оно совпадает с заданным адресом, то обработчик переходит в режим приема пакета. Если адрес не совпадает, то обработчик переходит в режим отвергания пакета. Если при приеме байта флаг таймера сброшен, то обработчик проверяет режим работы и либо принимает пакет, либо вываливается.
Сообщение отредактировал oran-be - Jul 31 2007, 05:27
|
|
|
|
|
Jul 31 2007, 05:46
|
Местный
  
Группа: Свой
Сообщений: 252
Регистрация: 14-09-06
Пользователь №: 20 377

|
МК Slave: Скажем есть функция обработки принятого пакета, запускается по таймауту таймера, рассчитываем КС, проверяем адрес, выбираем команду, в итоге код команды получен, как лучше дальше реализовать ветвление по командам, if, switch, т.е. перейти к обработке полученной команды. Сформировать пакет с ответом
|
|
|
|
|
Jul 31 2007, 06:53
|

Местный
  
Группа: Свой
Сообщений: 243
Регистрация: 22-09-04
Из: Burbach, Germany
Пользователь №: 704

|
Цитата(defunct @ Jul 30 2007, 23:15)  Ну не знаю как в PC (и надо ли оно вообще делать Modbus slave на PC). Порой приходится делать... Делал девайс, который работал под управлением процессорной платы ICOP (одноплатный 386-й) Так вот задачей было сгородить на нем Слейв Модбаса для связи со СКАДой. Плата работает под ДОС-ом, поэтому сказанное ниже некоторый оффтоп, но может кому пригодится идея... Основной проблемой было отловить 3.5-кратный интервал тишины на линии... Игра с таймером требуемого результата не принесла... Внимательно изучив описание стандартного УАРТа заметил (  ) очень "полезное" прерывание - по таймауту (4-х кратному интервалу передачи символа). Ну а дальше - дело техники... 1) Настраиваем ФИФО например на 16 символов. 2) Если возникает прерывание заполнения ФИФО (не таймаут) - вычитываем 16 байт в буфер и продолжаем ожидать "доприема" пакета. 3) Если возникает прерывание по таймауту - вычитываем байты из ФИФО и считаем, что пакет принят, переходим к его анализу. Естественно, это все не в основном цикле крутится - за все действия отвечают обработчики прерываний от СОМ-порта, выставляющие флаги, анализируемые основной программой.
|
|
|
|
|
Jul 31 2007, 09:53
|
Знающий
   
Группа: Свой
Сообщений: 506
Регистрация: 29-09-05
Из: Донецк
Пользователь №: 9 063

|
To _Алекс Прикрепил документ, где хорощо распиcаны алгоритмы приема.И то,кто как делает простенький рабочий примерчик свободно распространяемый поляком.Компилятор CCS.
|
|
|
|
|
Jul 31 2007, 10:15
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(_Алекс @ Jul 31 2007, 07:15)  или вы по приему байта с юарта сбрасываете счетчик таймера? Именно так. Только не сбрасываю, а запускаю заново (если таймер был запущен, то он будет перезапущен). Этот код у меня в конце обработчика прерывания RX: Код // initialize timeout timer TCCR2 = 0; // stop mb timeout timer TCNT2 = 0; // reset timeout timer TIMSK |= (1 << OCIE2); OCR2 = QuadCharInterval; // <-- вычисляется при инициализации UART'a TCCR2 = (1 << WGM21)|(1 << CS22)|(1 << CS20); // set prescaler to 1024 and run timer Цитата(oran-be @ Jul 31 2007, 07:55)  Я прпробовал на двум мамках - на одной оказался 91 байт, на другой - 173. Если длина пакета менее длины ФИФО, паузы не будет. Вот оно оказывается что... Спасибо за информацию! Цитата(ALexx @ Jul 31 2007, 09:53)  Порой приходится делать... Делал девайс, который работал под управлением процессорной платы ICOP (одноплатный 386-й) Так вот задачей было сгородить на нем Слейв Модбаса для связи со СКАДой. Плата работает под ДОС-ом, поэтому сказанное ниже некоторый оффтоп, но может кому пригодится идея... Знаю эти платы, на M6117. Неплохой вариант для быстрых решений если под рукой нет более подходящего железа.. Пока девайс на M6117 проходит стадию показухи, есть время чтобы сделать более подходящий девайс. Ну а по поводу программирования MB слейва под DOS, дык сложностей никаких не вижу, однозадачка как никак, настроил таймер на частоту кратную символам UART'a и все под контролем. В серийке M6117 чрезмерно дорого получается, особенно если брать готовые платы. Девайс на базе AVR'ки (напр m128) по возможностям (производительности) будет то же самое, по надежности и потреблению - лучше, плюс быстрее стартует (перестартует), и дешевле в разы.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|