Я использую Modbus RTU и пытаюсь выяснить, как рассчитать CRC16.
Мне не нужен пример кода. Мне просто любопытно по поводу механизма.
Я узнал, что базовый CRC - это полиномиальное деление слова данных, которое дополняется нулями в зависимости от длины полинома.
Следующий тестовый пример должен проверить правильность моего базового понимания:
- слово данных: 0100 1011
- полином: 1001 (х 3 + 1)
- дополняется 3 битами из-за наивысшего показателя степени x 3
- расчет: 0100 1011 000/1001 -> остаток: 011
Расчет.
01001011000
1001
0000011000
1001
01010
1001
0011
Edit1: До сих пор подтверждено Марком Адлером в предыдущих комментариях / ответах.
В поисках ответа Я видел много разных подходов с реверсированием, зависимостью от младшего или большого порядкового номера и т. Д., Которые изменяют результат из данного 011
.
Modbus RTU CRC16
Конечно, я бы хотел понять, как работают разные версии CRC, но мой основной интерес - просто понять, какой механизм здесь применяется. Насколько я знаю:
- x 16 + x 15 + x 2 + 1 - полином: 0x18005 или 0b11000000000000101
- начальное значение 0xFFFF
- пример сообщения в шестнадцатеричном виде: 01 10 C0 03 00 01
- CRC16 вышеприведенного сообщения в шестнадцатеричном виде: C9CD
Я рассчитал это вручную, как в примере выше, но я бы не хотел записывать это в двоичном виде в этом вопросе. Я предполагаю, что мое преобразование в двоичный файл является правильным. Чего я не знаю, так это как включить начальное значение - используется ли оно для дополнения слова данными вместо нулей? Или мне нужно поменять ответ? Что-то еще?
1-я попытка: заполнение 16 битами с нулями.
Вычисляем остаток в двоичном виде будет 1111 1111 1001 1011
, который равен FF9B
в шестнадцатеричном формате и неправильный для CrC16 / Modbus, но правильный для CRC16 / Bypass
2-я попытка: заполнение 16 битами из-за начального значения.
Вычисляем остаток в двоичном виде будет 0000 0000 0110 0100
, что является 0064
в шестнадцатеричном и неправильным
Было бы здорово, если бы кто-то мог объяснить или уточнить мои предположения. Честно говоря, я потратил много часов на поиск ответа, но каждое объяснение основано на примерах кода на C / C ++ или других, которые я не понимаю. Заранее спасибо.
EDIT1: Согласно этому сайту , "первая попытка" указывает на другой метод CRC16 с тем же полиномом, но другим начальным значением (0x0000), что говорит мне, что расчет должен быть правильным.
Как включить начальное значение?
РЕДАКТИРОВАТЬ2: Марк Адлерс Ответ делает свое дело. Однако теперь, когда я могу вычислить CRC16 / Modbus, осталось несколько вопросов для прояснения. Не нужно, но ценится.
A) Порядок вычислений будет: ...?
- 1-е применение RefIn для полного ввода (включая дополненные биты)
- 2nd
xor
InitValue с (в CRC16) для первых 16 бит
- 3-е применение RefOut для полного вывода / остатка (остаток максимум 16 бит в CRC16)
B) Обращаясь к RefIn и RefOut: всегда ли он отражает 8 битов для входа и все биты для вывода, тем не менее, я использую CRC8 или CRC16 или CRC32?
C) Что означают 3-й (чек) и 8-й (XorOut) столбец на веб-сайте, который я имею в виду? Последнее кажется довольно простым, я предполагаю, что оно применимо, вычисляя значение xor
после RefOut точно так же, как InitValue?