Как рассчитать CRC16 CCITT в PHP HEX?

Я пытаюсь использовать функцию PHP CRC16 CCITT для вычисления контрольной суммы.

Устройство отправляет мне ПАКЕТ с включенной контрольной суммой:

10 00 00 00 00 00 00 00 12 51 09 08 00 18 00 04 02 14 00 0c 00 0c 02 1c 00 02 00 00 00 00 00 00 a0 77

Контрольная сумма в конце: a0 77

я пытался использовать

Как рассчитать crc16 в php

Преобразование C в PHP для функции CRC16

Безуспешно вычисления CRC 16 возвращают: E6 F4 вместо a0 77

Я получаю правильную шестнадцатеричную информацию при поиске:

100000000000000012510908001800040214000c000c021c0002000000000000

на веб-сайте http://www.lammertbies.nl/comm/info/crc-calculation.html, но я не могу его воспроизвести. (обязательно выберите тип ввода HEX)

Не могли бы вы помочь мне понять, как получить CCITT crc16 строки шестнадцатеричных значений

100000000000000012510908001800040214000c000c021c0002000000000000

Я ищу контрольную сумму a0 77


person Drace    schedule 04.05.2015    source источник
comment
@mpromonet На сайте я упоминал: CRC-CCITT (0xFFFF) = 0xA077. мои извинения за то, что я не указал CCITT   -  person Drace    schedule 04.05.2015
comment
К вашему сведению, на самом деле это ложный CCITT CRC-16. Обычно его ошибочно называют CCITT CRC-16. Однако фактическая CCITT CRC-16 отражается с нулевой инициализацией. См. этот каталог CRC.   -  person Mark Adler    schedule 04.05.2015


Ответы (3)


Я смог создать ту же контрольную сумму с реализацией, как показано ниже:

define('CRC16POLYN', 0x1021);

function CRC16Normal($buffer) {
    $result = 0xFFFF;
    if (($length = strlen($buffer)) > 0) {
        for ($offset = 0; $offset < $length; $offset++) {
            $result ^= (ord($buffer[$offset]) << 8);
            for ($bitwise = 0; $bitwise < 8; $bitwise++) {
                if (($result <<= 1) & 0x10000) $result ^= CRC16POLYN;
                $result &= 0xFFFF;
            }
        }
    }
    return $result;
}

echo dechex(CRC16Normal(hex2bin('100000000000000012510908001800040214000c000c021c0002000000000000')));

Выше дает a077 на выходе.

Фрагмент кода найден на https://forums.digitalpoint.com/threads/php-define-function-calculate-crc-16-ccitt.2584389/

person zaak    schedule 04.05.2015
comment
Требуется PHP 5.4 .. спасибо, без ссылки я бы и не догадался! - person Drace; 04.05.2015

Я узнал из функции Deplhi, как это работает. Он получает массив байтов вместо шестнадцатеричной строки для выполнения задания. Вот код:

// $commands = [0x35, 0x02, 0x02, 0x00, 0x10, 0x03];       // => 0x5ba3
$commands = [0x44, 0x02, 0x02, 0x01, 0x10, 0x03];       // => 0x55c0
var_dump(dechex(getChecksum($commands)));

function getChecksum($byteArray) {
    $polynom = 0x8408;
    $in_crc = 0x0000;
    for ($i = 0; $i < sizeof($byteArray); $i++) {
        for ($n = 0; $n < 8; $n++) {
            if((($byteArray[$i] & 0x0001) ^ $in_crc) & 0x0001) 
                $in_crc = ($in_crc >> 1) ^ $polynom;
            else 
                $in_crc = $in_crc >> 1;
            $byteArray[$i] = $byteArray[$i] >> 1;
        }
        $result = $in_crc;
    }
    return $result;
}

Решение можно проверить с помощью этого онлайн-калькулятора CRC. Используется алгоритм CRC-16/KERMIT.

person Maxim Roman    schedule 13.12.2018

Поэтому я искал, как рассчитать контрольную сумму в соответствии с [ISO/IEC 13239], используя многочлен «1021» (шестнадцатеричный) и начальное значение «FFFF» (шестнадцатеричный). Я нашел эту ссылку, которая может вычислять многие типы CRC. После отправки моего ввода мне нужно было значение поля CRC-CCITT (0xFFFF), что-то вроде этого:

CRC CCITT 0xFFFF

Поэтому я взял функцию JS (в файле .js имя функции это CRCFFFF ), который вычислил CCITT и создал его PHP-версию.

function crcChecksum($str) {
    // The PHP version of the JS str.charCodeAt(i)
    function charCodeAt($str, $i) {
        return ord(substr($str, $i, 1));
    }

    $crc = 0xFFFF;
    $strlen = strlen($str);
    for($c = 0; $c < $strlen; $c++) {
        $crc ^= charCodeAt($str, $c) << 8;
        for($i = 0; $i < 8; $i++) {
            if($crc & 0x8000) {
                $crc = ($crc << 1) ^ 0x1021;
            } else {
                $crc = $crc << 1;
            }
        }
    }
    $hex = $crc & 0xFFFF;
    $hex = dechex($hex);
    $hex = strtoupper($hex);

    return $hex;
}

$result = crcChecksum('replace with your string here');// In my case, this gave me the desired output, which is '627B' (without '0x')

Если вам нужен «0x», просто добавьте его:

$result = '0x' . crcChecksum('replace with your string here');// result = '0x627B'
person evilReiko    schedule 19.11.2019