Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Свойства CRC16(Modbus)
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Вопросы системного уровня проектирования
AlexOr
Введение
1. Рассчитаем CRC16(Modbus) (см. тут On-line CRC calculation http://www.lammertbies.nl/comm/info/crc-calculation.html) от двух байт 0x01, 0х02. Получаем значение 0xE181.
2. А теперь рассчитаем CRC16(Modbus) от четырех байт 0x01, 0х02, 0x81, 0xE1 (добавили младший и старший от ранее рассчитанного CRC). Получаем значение 0x0000.
ДА именно 0x0000 и байты 0x01, 0х02 можно заменить на любые (при выполнении 1 и 2). Все равно будет 0x0000.
Что это за свойство и неужели все про него знают? Я не знал.
Как называется это свойство и вообще подобные свойства? Есть ли подобные свойства при другом полиноме? А у CRC32?


Итог
История применения CRC16(Modbus)
Был на скорую руку сделан протокол с разделением пакетов по специальному символу. Соответственно был применен байт-стаффинг. В общем, длина пакета определяется по количеству байт до специального символа и далее сразу рассчитывается CRC для проверки пакета. Было выявлено, что при наличии интенсивных помех в канале связи, происходит добавление нулей в принимаемую последовательность и иногда вместо приема 0x01, 0х02, 0x81, 0xE1 получатся прием 0x01, 0х02, 0x81, 0xE1, 0х00 , 0х00.
!!!!!!!!!!!!!!!!!!!!!!!!!!!
А так как мы считаем два последних байта значением CRC, то такой неверный пакет проходит как правильный.
!!!!!!!!!!!!!!!!!!!!!!!!!!!
MrYuran
Цитата(AlexOr @ Jul 20 2010, 09:07) *
А теперь рассчитаем CRC16(Modbus) от четырех байт 0x01, 0х02, 0x81, 0xE1 (добавили младший и старший от ранее рассчитанного CRC). Получаем значение 0x0000.
ДА именно 0x0000 и байты 0x01, 0х02 можно заменить на любые. Все равно будет 0x0000.

Вот это место осветите подробнее.
Что-то у вас в консерватории не то.
Если вы измените байты, изменится и ЦРЦ.
alexander55
ТС, Вы неправильно считаете CRC. Советую, взять контрольные примеры и отладить свой алгоритм.
Если будут проблемы, то можно что-то найти из примеров.
AlexOr
Цитата(MrYuran @ Jul 20 2010, 09:18) *
Вот это место осветите подробнее.

Дабавил пункты 1 и 2.

Цитата(alexander55 @ Jul 20 2010, 09:28) *
ТС, Вы неправильно считаете CRC. Советую, взять контрольные примеры и отладить свой алгоритм.

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

Цитата(MrYuran @ Jul 20 2010, 09:18) *
Если вы измените байты, изменится и ЦРЦ.

0х03, 0х04 CRC(Modbus) равна 0x8300
0х03, 0х04, 0х00, 0х83 CRC(Modbus) равна 0х0000 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
alexander55
Цитата(AlexOr @ Jul 20 2010, 09:32) *

Нашел примеры от Шнайдера (считайте, законодателя модбаса - модикона).
Проверяйте реализацию алгоритма.
01 03 0C00 0002 (C75B)
01 03 04 0000 0000 (FA33)
01 03 02 1234 (B533)
Хватит для тестирования.
VslavX
Цитата(AlexOr @ Jul 20 2010, 08:07) *
ДА именно 0x0000 и байты 0x01, 0х02 можно заменить на любые (при выполнении 1 и 2). Все равно будет 0x0000.

Именно так - всегда будет ноль. Это свойство СRC как остатка от полиномиального деления. То есть - вы взяли произвольную битовую последовательность, поделили ее на полином, получили некоторый остаток (пункт 1 в Вашем описании). Потом Вы взяли получившийся остаток добавили к последовательности и снова поделили, результирующий остаток ессно будет ноль.
Если привести аналогию (не совсем корректную) к обычной (не полиномиальной арифметике). То у Вас было число S (исходная последовательность), Вы его поделили на некоторое P (полином), получили остаток D. То есть S = N*P + D. А потом Вы вычли из S остаток D и получили новое число S' = S-D. Ессно S' будет нацело делиться на P и остаток всегда будет 0. И при такой операции совершенно неважно какое у Вас было изначальное S - итоговый остаток всегда 0.
AlexOr
Цитата(alexander55 @ Jul 20 2010, 09:39) *
Проверяйте реализацию алгоритма.
01 03 0C00 0002 (C75B)

Согласно онлайн калькулятору
0x01, 0x03, 0x0c, 0x00, 0x00, 0x02 имеет CRC(Modbus) 0x5BC7
т.е. все правильно
и не надо разводить не по существу.
alexander55
Цитата(AlexOr @ Jul 20 2010, 09:53) *
Согласно онлайн калькулятору
0x01, 0x03, 0x0c, 0x00, 0x00, 0x02 имеет CRC(Modbus) 0x5BC7
т.е. все правильно

Ясно, без этой проверки говорить было бы бессмысленно.
Теперь по существу вопроса.
КС находится в конце пакета принятого. А новый пакет пока не пошел. Адрес 00 не рекомендуется использовать (если Вы внимательно почитаете мануалы). Проблем нет.
AlexOr
Цитата(VslavX @ Jul 20 2010, 09:51) *
Именно так - всегда будет ноль. Это свойство СRC как остатка от полиномиального деления. То есть - вы взяли произвольную битовую последовательность, поделили ее на полином, получили некоторый остаток (пункт 1 в Вашем описании). Потом Вы взяли получившийся остаток добавили к последовательности и снова поделили, результирующий остаток ессно будет ноль.

В пакете протокола Modbus передается сначала старший байт CRC в отличии от моего формирования пакета. Я правильно понимаю, что такое решение Modbus позволяет полностью обойти данную проблему?

Цитата(alexander55 @ Jul 20 2010, 10:03) *
Ясно, без этой проверки говорить было бы бессмысленно.

Ясно что Вам нечего сказать.


MrYuran
Цитата(AlexOr @ Jul 20 2010, 09:38) *
0х03, 0х04 CRC(Modbus) равна 0x8300
0х03, 0х04, 0х00, 0х83 CRC(Modbus) равна 0х0000 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Ну да, так и должно быть.
Ноль означает отсутствие ошибок.
Неноль - ошибка.

Пока так и не понимаю, в чём заключается ваша проблема.
Хотя, кажется, догадываюсь.
Если в пакет включаются нули, они не оказывают влияния на ЦРЦ, а пакет искажают.
В том же модбасе есть поле длины пакета, по которому такие пакеты можно однозначно вычислить.
То есть, проверяется целостность пакета и CRC
Если не совпало - пакет битый.
Вам наверно лучше подойдёт модбас ASCII, он как раз с маркером начала и конца пакета
Кроме того, принимаемые байты должны соответствовать строго определённым ASCII-символам, что даёт дополнительную защиту, от тех же нулей, например
alexander55
Цитата(AlexOr @ Jul 20 2010, 10:12) *
Ясно что Вам нечего сказать.

Очень эмоционально.
Навеяло. biggrin.gif
Что же тебе сказать, если ты ничего не говоришь (ц).
ЗЫ.
Обычно проблемы бывают, когда низкий процент прохождения пакетов в условиях повышенной помеховой обстановки. Проблему решают подтверждением прохождения пакетов и повторной отправкой пакета в случае его непрохождения. С достоверностью принятых пакетов проблем никогда не возникало.
Oldring
Цитата(AlexOr @ Jul 20 2010, 09:07) *
Что это за свойство и неужели все про него знают? Я не знал.
Как называется это свойство и вообще подобные свойства? Есть ли подобные свойства при другом полиноме? А у CRC32?


Ну изучите значит теорию, чтобы знать. Таким свойством обладают любые линейные циклические коды. В случае CRC иногда инвертируют проверочные символы, в этом случае дописывание произвольного количества нулей в конце детектируется, но не в случае Модбаса.

И вообще говоря, CRC-16 не очень подходит для линий с высоким уровнем шума. Слишком мало проверочных битов. Велика вероятность пропустить групповую ошибку.
i-mir
Цитата(AlexOr @ Jul 20 2010, 08:07) *
добавили младший и старший от ранее рассчитанного CRC. Получаем значение 0x0000.


Тема была давно, но суть не меняется.

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

Так вот задумка и была таковой, что остаток CRC добавлялся передатчиком к концу посылки,
и приемник вычисляя CRC на ходу, принимал данные и остаток - получал 0. По этому факту
посылка или принималась или отбраковывалась тут-же. Очень просто и красиво.

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




Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.