Я пытаюсь вычислить CRC для уровня связи DNP3. В спецификации говорится, что это двухоктетный CRC, основанный на полиноме X ^ 16 + X ^ 13 + X ^ 12 + X ^ 11 + X ^ 10 + X ^ 8 + X ^ 6 + X ^ 5 + X ^ 2 + 1. Он также инвертируется и помещается в блок данных LSB первым.

В пакете Perl's Digest я настроил алгоритм следующим образом:

my $ctx = Digest::CRC->new(width=>16, init=>0, xorout=>0xffff, refin=>1, refout=>1, poly=>0x3d65, cont=>0xea82);

$ctx->add(0x05);
$ctx->add(0x64);
$ctx->add(0x05);
$ctx->add(0xF2);
$ctx->add(0x01);
$ctx->add(0x00);
$ctx->add(0x00);
$ctx->add(0x00);

my $x=$ctx->digest;
printf("x=%04x\n",$x);

Пример в спецификации, показанный для заголовка: 05 64 05 F2 01 00 00 00 контрольная сумма должна быть 52 0C. Получаю x = 91fc.

Я пробовал поиграть со всеми параметрами, но, похоже, не получается. Какие-либо предложения? Нужно ли мне добавлять () побайтно данные? слово (2 байта) по слову?

2
wdtj 6 Сен 2016 в 23:27

2 ответа

Лучший ответ

Хорошо, с вашей небольшой помощью, взломав Digest :: CRC и пошагово сравнивая результаты расчетов CRC C Sample в IEEE Std 1815, я придумал следующий код:

my $ctx = Digest::CRC->new(width=>16, init=>0, xorout=>0xffff, refin=>1, refout=>1, poly=>0x3d65, cont=>0);

$ctx->add(chr(0x05));
$ctx->add(chr(0x64));
$ctx->add(chr(0x05));
$ctx->add(chr(0xF2));
$ctx->add(chr(0x01));
$ctx->add(chr(0x00));
$ctx->add(chr(0x00));
$ctx->add(chr(0x00));

my $x=$ctx->digest;
printf("x=%02X %02X\n",$x>>8, $x&0xFF);

Проблема с моим исходным кодом была не в дайджесте CRC, а в том, как я передавал данные в модуль. Я передал его как одно скалярное значение. Затем Digest :: CRC добавит это в буфер данных с кодом:

$self->{_data} .= join '', @_ if @_;

Это (очевидно) преобразовало скаляр в строку (т.е. 0x05 в "5"). Далее идет подпрограмма дайджеста, которая обращается к первому байту с кодом:

ord(substr($message, $pos++, 1))

Это привело к перевариванию значения 0x35, а не 0x05, как я планировал.

Решением было передать данные в модуль, обернув данные в виде строки (т.е. chr (0x05)).

Спасибо всем, особенно gammatester и dasgar, за то, что указали мне правильное направление.

0
wdtj 8 Сен 2016 в 13:08

Ваши данные совместимы с CRC-16 / DNP из http: / /reveng.sourceforge.net/crc-catalogue/16.htm

width=16  
poly=0x3d65  
init=0x0000  
refin=true  
refout=true 
xorout=0xffff  
check=0xea82  
name="CRC-16/DNP"

Вы можете проверить это с помощью https://www.lammertbies.nl/comm/info/. crc-calculate.html

1
gammatester 7 Сен 2016 в 07:46