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

Калькулятор CRC

Вставьте байты в шестнадцатеричном виде или текст и выберите алгоритм — калькулятор посчитает CRC, покажет порядок байтов в кадре и сгенерирует функцию на C: компактную побитовую или быструю табличную. Для своего протокола задайте параметры вручную.

Исходные данные

Он же MODBUS

Данные

01 03 00 0A, 0x01,0x03 или 01030A

Результат

CRC-16/MODBUS
0xCDC5
52677 в десятичной записи, 6 байт данных
Байты CRC в кадре
C5 CDмладший байт первым, как требует протокол
Кадр с CRC
01 03 00 00 00 0A C5 CD
В двоичном виде
1100 1101 1100 0101
Проверка «123456789»
0x4B37совпадает с каталогом CRC RevEng
Код на C
#include <stddef.h>
#include <stdint.h>

/* CRC-16/MODBUS: width 16, poly 0x8005, init 0xFFFF, refin true, refout true, xorout 0x0000, check 0x4B37 */
uint16_t crc16_modbus(const uint8_t *data, size_t len)
{
    uint16_t crc = 0xFFFF;

    while (len--) {
        crc ^= *data++;
        for (int i = 0; i < 8; i++)
            crc = (crc & 1) ? (uint16_t)((crc >> 1) ^ 0xA001) : (uint16_t)(crc >> 1);
    }
    return (uint16_t)(crc ^ 0x0000);
}

CRC (циклический избыточный код) — контрольная сумма, которую передатчик дописывает в конец кадра, а приёмник пересчитывает по принятым данным. Математически это остаток от деления сообщения как двоичного многочлена на порождающий полином. CRC обнаруживает любую одиночную ошибку и любой пакет ошибок не длиннее разрядности CRC, а если полином делится на x + 1 — ещё и все ошибки с нечётным числом искажённых битов. Двойные ошибки CRC ловит гарантированно, только пока кадр короче периода полинома, поэтому полином выбирают под длину данных.

Параметры алгоритма

Любой распространённый CRC описывается шестью параметрами модели Rocksoft (Р. Уильямс, 1993):

ПараметрЧто задаётCRC-16/MODBUS
Widthразрядность CRC, бит16
Polyпорождающий полином без старшего бита0x8005
Initначальное значение регистра0xFFFF
RefInобрабатывать ли каждый байт младшим битом вперёдда
RefOutперевернуть ли биты результатада
XorOutс чем сложить по модулю 2 результат0x0000

Полином записывают без старшего бита: 0x8005 означает x¹⁶ + x¹⁵ + x² + 1. Отражённый алгоритм работает с перевёрнутым полиномом и сдвигает регистр вправо — поэтому в коде Modbus фигурирует 0xA001, а в коде CRC-32 — 0xEDB88320.

Одного полинома мало: CRC-16/CCITT-FALSE, CRC-16/KERMIT и CRC-16/XMODEM используют один и тот же 0x1021, но дают разные результаты. Для проверки служит контрольное значение — CRC от строки «123456789»; у каждого пресета калькулятор сверяет его с каталогом CRC RevEng.

Популярные алгоритмы

АлгоритмPolyInitRefIn/RefOutXorOutCheckГде используется
CRC-8/SMBUS0700нет00F4SMBus
CRC-8/MAXIM-DOW3100да00A11-Wire, DS18B20
CRC-8/NRSC-531FFнет00F7датчики Sensirion
CRC-16/MODBUS8005FFFFда00004B37Modbus RTU
CRC-16/IBM-3740 (CCITT-FALSE)1021FFFFнет000029B1многие протоколы
CRC-16/XMODEM10210000нет000031C3XMODEM, карты SD
CRC-16/KERMIT (CCITT)10210000да00002189Kermit, Bluetooth
CRC-15/CAN45990000нет0000059Eкадр CAN 2.0
CRC-32 (ISO-HDLC)04C11DB7FFFFFFFFдаFFFFFFFFCBF43926ZIP, PNG, Ethernet
CRC-32C1EDC6F41FFFFFFFFдаFFFFFFFFE3069283iSCSI, ext4
CRC-32/MPEG-204C11DB7FFFFFFFFнет000000000376E6E7MPEG-2, блок CRC в STM32

Все значения в шестнадцатеричном виде.

Modbus RTU

В Modbus RTU CRC считают по всем байтам кадра, начиная с адреса устройства. Регистр начинается с FFFF, на каждый байт выполняется XOR и восемь сдвигов вправо с полиномом A001, результат дописывают младшим байтом вперёд. Запрос «прочитать 10 регистров хранения, начиная с нулевого, у устройства 1» выглядит так: 01 03 00 00 00 0A C5 CD.

Приёмнику не нужно сравнивать CRC отдельно: если посчитать CRC-16/MODBUS по всему кадру вместе с двумя последними байтами, при правильной передаче получится ноль. Про физический уровень Modbus — в статье о RS-485.

1-Wire и датчики

У 1-Wire последний байт 64-битного ROM-кода — CRC-8 полинома X⁸ + X⁵ + X⁴ + 1 (0x31) по первым семи байтам; той же CRC защищён блокнот DS18B20. Байты обрабатываются младшим битом вперёд, поэтому в каталоге это CRC-8/MAXIM-DOW с отражением. Датчики Sensirion используют тот же полином, но без отражения и с начальным значением FF: по даташиту SHT3x CRC от байтов BE EF равна 0x92. Подробнее о шине — в статье об 1-Wire.

STM32 и порядок байтов

Аппаратный блок CRC у STM32 по умолчанию считает с полиномом 0x04C11DB7 и начальным значением 0xFFFFFFFF без отражения и финального XOR — это параметры CRC-32/MPEG-2, а не «обычного» CRC-32 из ZIP. К тому же блок принимает 32-битные слова и обрабатывает каждое старшим битом вперёд. Если записывать в него байты потока словами на little-endian процессоре, порядок байтов внутри слова окажется обратным, и результат разойдётся с расчётом по байтам. Сверяйте результат по контрольному значению или подавайте данные побайтно, если блок это позволяет.

Какой код выбрать

  • Побитовый — восемь итераций на байт и ни одной таблицы. Подходит для коротких кадров Modbus и 1-Wire на маленьком МК.
  • Табличный — один поиск в таблице на байт. Таблица на 256 значений занимает 256 байт для CRC-8, 512 байт для CRC-16 и 1 КБ для CRC-32 во флеш-памяти.

Сгенерированный код проверен: все пресеты калькулятора в обоих вариантах собраны компилятором MSVC с предупреждениями уровня 4 как ошибками и дают контрольное значение каталога. Функция принимает указатель на данные и длину и возвращает готовую CRC — с отражением и финальным XOR, если они нужны.

Если протокол свой, полином лучше брать из таблиц Ф. Купмана: он подобрал полиномы с наибольшим расстоянием Хэмминга для каждой длины данных.

Частые вопросы

Как посчитать CRC-16 для Modbus RTU?

Выберите CRC-16/MODBUS и вставьте байты кадра без CRC, например 01 03 00 00 00 0A. Получится 0xCDC5, а в кадр байты идут младшим вперёд: 01 03 00 00 00 0A C5 CD. Начальное значение регистра — FFFF, полином в отражённом виде — A001, финального XOR нет. Если посчитать CRC по всему принятому кадру вместе с двумя байтами CRC, должен получиться ноль.

Чем CRC-16/CCITT-FALSE отличается от CRC-16/CCITT?

У обоих полином 0x1021, но остальные параметры разные. CCITT-FALSE (в каталоге — CRC-16/IBM-3740) начинается с FFFF и обрабатывает биты старшим вперёд, контрольное значение 0x29B1. CRC-16/CCITT, он же KERMIT, начинается с нуля и работает с отражёнными байтами, контрольное значение 0x2189. Есть ещё XMODEM — ноль в начале без отражения, 0x31C3. Названия в разных библиотеках путают, поэтому сверяйте контрольное значение для строки «123456789».

Что такое контрольное значение check?

Это CRC от девяти ASCII-символов «123456789» — байты 31 32 33 34 35 36 37 38 39. По нему однозначно проверяют, что реализация и параметры совпадают с эталоном: у CRC-32 это 0xCBF43926, у CRC-16/MODBUS — 0x4B37. Калькулятор показывает check для выбранных параметров и сверяет его с каталогом CRC RevEng.

Что такое отражение входа и результата?

Отражение (RefIn) означает, что каждый байт обрабатывается младшим битом вперёд — так передаёт UART, поэтому отражённые CRC естественны для последовательных протоколов. RefOut переворачивает биты готового результата. В программе отражённый алгоритм сдвигает регистр вправо и использует перевёрнутый полином: для 0x8005 это 0xA001, для CRC-32 — 0xEDB88320.

Табличный или побитовый расчёт CRC — что выбрать?

Побитовый алгоритм — несколько строк без таблицы, но 8 итераций цикла на каждый байт. Табличный обрабатывает байт за одну операцию, зато таблица занимает 256 значений: 256 байт для CRC-8, 512 для CRC-16 и 1 КБ для CRC-32 во флеш-памяти. На маленьком МК с короткими кадрами Modbus хватает побитового варианта, для потоков данных и CRC-32 выгоднее таблица.

Источники

  1. Ross N. Williams. A Painless Guide to CRC Error Detection Algorithms. 1993 — модель параметров Width, Poly, Init, RefIn, RefOut, XorOut; прямой и табличный алгоритмы
  2. Greg Cook. Catalogue of parametrised CRC algorithms (CRC RevEng) — параметры, псевдонимы и контрольные значения всех пресетов калькулятора
  3. Modbus Organization. MODBUS over Serial Line: Specification and Implementation Guide V1.02 — CRC в режиме RTU: начальное значение FFFF, полином A001, младший байт первым
  4. Maxim Integrated. Application Note 27: Understanding and Using Cyclic Redundancy Checks with Maxim 1-Wire and iButton Products — CRC-8 полинома X⁸ + X⁵ + X⁴ + 1 в ROM-коде 1-Wire
  5. Sensirion. Datasheet SHT3x-DIS, version 7, 2022 — CRC-8: полином 0x31, начальное значение 0xFF, пример CRC(0xBEEF) = 0x92
  6. STMicroelectronics. AN4187: Using the CRC peripheral in the STM32 family, rev. 2, 2022 — аппаратный блок CRC: полином 0x04C11DB7, начальное значение 0xFFFFFFFF, обработка 32-битных слов
  7. Philip Koopman. Best CRC Polynomials — выбор полинома по расстоянию Хэмминга для заданной длины данных

Обновлено . Нашли ошибку в расчёте? Напишите нам.