【问题标题】:How to calculate CRC16 CCITT in PHP HEX?如何在 PHP HEX 中计算 CRC16 CCITT?
【发布时间】:2015-05-04 16:55:14
【问题描述】:

我正在尝试使用 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

我试过了

How to calculate crc16 in php

Convert C to PHP for CRC16 Function

如果没有成功,CRC 16 计算返回:E6 F4 而不是 a0 77

当我查找时,我得到了正确的十六进制信息:

100000000000000012510908001800040214000c000c021c0002000000000000

http://www.lammertbies.nl/comm/info/crc-calculation.html 网站上,但我无法复制它。 (确保选择输入类型为 HEX)

你能帮我弄清楚如何获取十六进制值字符串的crc16 CCITT

100000000000000012510908001800040214000c000c021c0002000000000000

我正在寻找校验和a0 77

【问题讨论】:

  • @mpromonet 在我提到的网站上:CRC-CCITT (0xFFFF) = 0xA077。我很抱歉没有指定 CCITT
  • 仅供参考,这实际上是“假”CCITT CRC-16。它通常被误认为是 CCITT CRC-16。然而,实际的 CCITT CRC-16 反映为零初始化。见this catalogue of CRCs

标签: php hex crc crc16


【解决方案1】:

我能够通过如下实现产生相同的校验和:

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的输出。

代码 sn-p 在https://forums.digitalpoint.com/threads/php-define-function-calculate-crc-16-ccitt.2584389/找到

【讨论】:

  • 需要 PHP 5.4.. 谢谢,如果没有链接,我不会知道!
【解决方案2】:

我从 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;
}

解决方案可以在this 在线CRC计算器上得到证明。 使用的算法是 CRC-16/KERMIT

【讨论】:

    【解决方案3】:

    所以我一直在寻找如何根据 [ISO/IEC 13239] 使用多项式“1021”(十六进制)和初始值“FFFF”(十六进制)来计算校验和。我发现了这个link,它可以计算多种类型的CRC。提交输入后,我想要字段CRC-CCITT (0xFFFF) 的值,如下所示:

    于是我取了计算CCITT的JS函数(在.js file中,函数名为CRCFFFF),并创建了它的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'
    

    【讨论】:

      猜你喜欢
      • 2020-10-27
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 2017-02-11
      • 2021-08-12
      相关资源
      最近更新 更多