Расчет FCS(CRC) для кадра HDLC

У меня есть следующий кадр:

7e  01 00  00  01  00  18  ef  00  00  00   b5   20 c1 05 10 02 71 2e 1a c2 05 10 01 71 00 6e 87 02 00 01 42 71 2e 1a 01 96 27 be 27 54 17 3d b9 93 ac 7e

Если я правильно понимаю, то именно эта часть кадра рассчитана для FCS:

010000010018ef000000b520c1051002712e1ac205100171006e8702000142712e1a019627be2754173db9

Я пытался ввести это в число онлайн-калькуляторов, но я не могу произвести 0x93ac из приведенных выше данных.

http://www.lammertbies.nl/comm/info/crc-calculation.html с типом ввода hex.

Как получается 0x93ac?

Спасибо,

Барри

4 ответа

Решение

Прежде всего, значение CRC 0xac93

Используйте этот калькулятор: http://www.zorc.breitbandkatze.de/crc.html

  • Установить порядок CRC 16
  • Полином 1021
  • Начальное значение ffff
  • Конечное значение ffff
  • "обратные байты данных"
  • "Обратный результат CRC до финального XOR"
  • Введите вашу последовательность как:

    %01%00%00%01%00%18%ef%00%00%00%b5%20%c1%05%10%02%71%2e%1a%c2%05%10%01%71%00%6e%87%02%00%01%42%71%2e%1a%01%96%27%be%27%54%17%3d%b9
    
  • Нажмите "Рассчитать" и вы получите 0xAC93

Отвечая скорее на тех, кто попал сюда во время поиска совета.

Ключевым моментом является то, что несколько пунктов в тесно связанных рекомендациях МСЭ-Т (например, Q.921, которые доступны в сети уже довольно давно) говорят:

1. бит самого низкого порядка передается (и, таким образом, принимается) первым

Это унаследованное поведение противоречит обычным правилам повседневной жизни, когда цифры высшего порядка записываются первыми в порядке чтения, а все общие онлайн-калькуляторы и библиотеки выполняют вычисления с использованием обычного порядка и предоставляют необязательные настройки для упрощения обратного. Поэтому вы должны спросить онлайн калькулятор

  • перед выполнением вычисления изменить порядок бит в сообщении, которое вы вводите в "обычном" формате,
  • изменить порядок следования битов результата, чтобы получить их в том же порядке, что и в самом сообщении

Вполне разумно, что некоторые калькуляторы предлагают только одну общую настройку для обоих.

Это приводит к тому, что настройки "обратные байты данных" и "обратный результат CRC перед финальным XOR" рекомендуются в предыдущем ответе;

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

Битовая инверсия - это еще одно название "xor by 0xffff...". Есть цель инвертировать биты результата вычисления CRC перед отправкой его в качестве сообщения FCS (последние два байта сообщения, '93 ac'в вашем примере). Смотрите пункт 4 для деталей.

Это обусловливает настройку "Конечное значение ffff", имя которой вводит в заблуждение, так как фактически определяет шаблон для xor'ed с результатом вычисления. Поскольку такая операция требуется для нескольких типов CRC, только шаблоны xor варьируются от 0 (без операции) до 0xfff... (полная инверсия), универсальные калькуляторы / библиотеки предлагают его для простоты использования.

3. расчет должен включать обработку ведущей последовательности 0xffff

Это обосновывает пункт "начальное значение ffff".

4. на принимающей (проверяющей) стороне рекомендуется протолкнуть полное сообщение, т. Е. Включая FCS, через вычисление CRC, и ожидать, что результат будет 0x1d0f.

За этим стоит некое умное мышление:

  • внутреннее свойство алгоритма CRC заключается в том, что

    CRC( x.CRC(x))

    всегда 0 (x представляет исходное сообщение, а "." представляет конкатенацию).

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

  • однако слишком легко допустить ошибку кодирования, в результате чего результат становится равным 0. К счастью, благодаря внутренним свойствам алгоритма CRC,

    CRC (x. (CRC (x)) ')

    дает постоянное значение, не зависящее от x и отличное от 0 (по крайней мере для CRC-CCITT, о котором мы поговорим здесь). Знак "" представляет инверсию битов, требуемую в пункте 2.

Это простой скрипт Python для вычисления CRC HDLC. Вы можете это для DLMS

def byte_mirror(c):

    c = (c & 0xF0) >> 4 | (c & 0x0F) << 4
    c = (c & 0xCC) >> 2 | (c & 0x33) << 2
    c = (c & 0xAA) >> 1 | (c & 0x55) << 1

    return c

CRC_INIT=0xffff
POLYNOMIAL=0x1021
DATA_VALUE=0xA0

SNRM_request=[ 0x7E, 0xA0, 0x08, 0x03, 0x02, 0xFF, 0x93, 0xCA, 0xE4, 0x7E]

print("sent>>", end=" ")

for x in SNRM_request:
  if x>15:
       print(hex(x), end=" ")
  else:
       a=str(hex(x))
       a = a[:2] + "0" + a[2:]
       print(a, end=" ")

lenn=len(SNRM_request)
print(" ")

crc = CRC_INIT



for i in range(lenn):

    if( (i!=0) and (i!=(lenn-1)) and (i!=(lenn-2)) and (i!=(lenn-3)) ):

        print("i>>",i)

        c=SNRM_request[i]
        c=byte_mirror(c)
        c = c << 8

        print(hex(c))

        for j in range(8):

            print(hex(c))
            print("CRC",hex(crc))

            if (crc ^ c) & 0x8000:
                crc = (crc << 1) ^ POLYNOMIAL
            else:
                crc = crc << 1

            c = c << 1   
            crc=crc%65536
            c  =c%65536


print("CRC-CALC",hex(crc))

crc=0xFFFF-crc          
print("CRC- NOT",hex(crc))

crc_HI=crc//256
crc_LO=crc%256

print("CRC-HI",hex(crc_HI))
print("CRC-LO",hex(crc_LO))

crc_HI=byte_mirror(crc_HI)
crc_LO=byte_mirror(crc_LO)

print("CRC-HI-zrc",hex(crc_HI))
print("CRC-LO-zrc",hex(crc_LO))

crc=256*crc_HI+crc_LO
print("CRC-END",hex(crc))

Для будущих читателей в приложении C к RFC1662 есть код для расчета FCS для HDLC.

Другие вопросы по тегам