Контрольная сумма CRC16: HCS08 против Kermit против XMODEM

Я пытаюсь добавить обнаружение ошибок CRC16 в приложение микроконтроллера Motorola HCS08. Хотя мои контрольные суммы не совпадают. Один онлайн CRC калькулятор обеспечивает как результат, который я вижу в своей программе ПК, так и результат, который я вижу на микро.

Он вызывает результат микро " XModem "и результат ПК" Kermit."

в чем разница между тем, как эти два древних протокола определяют использование CRC16?

3 ответов


вы можете реализовать 16 бит IBM, CCITT, XModem, Kermit и CCITT 1D0F, используя ту же базовую базу кода. см.http://www.acooke.org/cute/16bitCRCAl0.html который использует код из http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code

в следующей таблице показано, как они отличаются:

name    polynomial  initial val  reverse byte?  reverse result?  swap result?
CCITT         1021         ffff             no               no            no
XModem        1021         0000             no               no            no
Kermit        1021         0000            yes              yes           yes
CCITT 1D0F    1021         1d0f             no               no            no
IBM           8005         0000            yes              yes            no

где "обратный байт" означает, что каждый байт перед обработкой отменяется; "обратный результат" означает, что результат 16 бит бит-обратный после обработки; "результат подкачки" означает, что два байта в результате меняются местами после обработки.

все вышеперечисленное было подтверждено тестовыми векторами против http://www.lammertbies.nl/comm/info/crc-calculation.html (Если это неправильно, мы все потеряны...).

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

[Я считаю, но не проверил или не разработал детали, что обращение каждого байта эквивалентно обращению полинома (плюс некоторые дополнительные детали). вот почему вы увидите очень разные объяснения в разных местах для того, что в основном является одним и тем же алгоритмом.

кроме того, подход выше не эффективен, но хорош для тестирования. если вы хотите эффективно, лучше всего перевести вышеизложенное на таблица поиска.]

редактировать то, что я назвал CCITT выше, документировано в каталог Ревенг как CCITT-FALSE. для получения дополнительной информации см. обновление моего сообщения в блоге по ссылке выше.


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

большинство программных реализаций CRC (xmodem, вероятно) сначала проходят через байты данных, наиболее значительные бит.

при просмотре источника библиотеки (загрузите его из http://www.lammertbies.nl/comm/software/index.html) используется для страницы расчета CRC, с которой вы связаны, вы увидите, что XModem использует CRC16-CCITT, многочлен для которого:

x^16 + x^12 + x^5 + 1  /* the '^' character here represents exponentition, not xor */

полином представлен растровым изображением (обратите внимание, что бит 16 подразумевается)

0x1021 == 0001 0000 0010 0001  binary

реализация Kermit использует:

0x8408 == 1000 0100 0000 1000  binary

что же растровое изображение как xmodem, только обратная.

в текстовом файле, сопровождающем библиотеку, также упоминается следующее различие для Kermit:

только для CRC-Kermit и CRC-SICK: после обработки всех входных данных, вычисляется дополнение одного CRC, и два байта CRC меняются местами.

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


X-Modem 1K CRC16.

процесс для bytewise CRC-16 с использованием входных данных {0x01, 0x02} и полинома 0x1021

  1. Init crc = 0
  2. обрабатывать первый входной байт 0x01: 2.1' Xor-in ' первый входной байт 0x01 в MSB (!) КПР: 0000 0000 0000 0000 (crc) 0000 0001 0000 0000 (входной байт 0x01 сдвинут влево на 8)


    0000 0001 0000 0000 = 0x0100 MSB этого результата - наш текущий делитель: MSB (0x100) = 0x01. 2.2 так 0х01-это дивидент. Получите остаток для делителя из нашей таблицы: crctable16[0x01] = 0x1021. (Ну, это значение famila из ручного вычисления выше.) Помните, что текущее значение crc равно 0x0000. Сдвиньте MSB текущего crc и xor его с текущим остатком, чтобы получить новый CRC: 0001 0000 0010 0001 (0x1021) 0000 0000 0000 0000 (CRC 0x0000 смещен влево на 8 = 0x0000)


    0001 0000 0010 0001 = 0x1021 = промежуточный crc.

  3. обрабатывать следующий вход байт 0x02: В настоящее время мы имеем промежуточный КПР = 0x1021 = 0001 0000 0010 0001. 3.1' Xor-in ' входной байт 0x02 в MSB (!) КПР: 0001 0000 0010 0001 (crc 0x1021) 0000 0010 0000 0000 (входной байт 0x02 сдвигается влево на 8)


    0001 0010 0010 0001 = 0x1221 MSB этого результата - наш текущий делитель: MSB (0x1221) = 0x12. 3.2 так 0x12 это дивидент. Получите остаток для делителя из нашей таблицы: crctable16[0x12] = 0x3273. Помните, что текущее значение crc равно 0x1021. Shift out MSB текущего crc и xor его с текущим остатком, чтобы получить новый CRC: 0011 0010 0111 0011 (0x3273) 0010 0001 0000 0000 (CRC 0x1021 смещен влево на 8 = 0x2100)


    0001 0011 0111 0011 = 0x1373 = окончательный crc.