Last active
August 23, 2019 17:30
-
-
Save hainuo/d84a084fe899e17e466573c752df29a7 to your computer and use it in GitHub Desktop.
php crc16校验值
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// 来源 经测试是正确的 https://blog.csdn.net/zhang197093/article/details/89061957 | |
// 增加一个crc在线校验监测网址 http://www.ip33.com/crc.html | |
/** | |
* 将一个字符按比特位进行反转 eg: 65 (01000001) --> 130(10000010) | |
* @param $char | |
* @return $char | |
*/ | |
function reverseChar($char) { | |
$byte = ord($char); | |
$tmp = 0; | |
for ($i = 0; $i < 8; ++$i) { | |
if ($byte & (1 << $i)) { | |
$tmp |= (1 << (7 - $i)); | |
} | |
} | |
return chr($tmp); | |
} | |
/** | |
* 将一个字节流按比特位反转 eg: 'AB'(01000001 01000010) --> '\x42\x82'(01000010 10000010) | |
* @param $str | |
*/ | |
function reverseString($str) { | |
$m = 0; | |
$n = strlen($str) - 1; | |
while ($m <= $n) { | |
if ($m == $n) { | |
$str{$m} = reverseChar($str{$m}); | |
break; | |
} | |
$ord1 = reverseChar($str{$m}); | |
$ord2 = reverseChar($str{$n}); | |
$str{$m} = $ord2; | |
$str{$n} = $ord1; | |
$m++; | |
$n--; | |
} | |
return $str; | |
} | |
/** | |
* @param string $str 待校验字符串 | |
* @param int $polynomial 二项式 | |
* @param int $initValue 初始值 | |
* @param int $xOrValue 输出结果前异或的值 | |
* @param bool $inputReverse 输入字符串是否每个字节按比特位反转 | |
* @param bool $outputReverse 输出是否整体按比特位反转 | |
* @return int | |
*/ | |
function crc16($str, $polynomial, $initValue, $xOrValue, $inputReverse = false, $outputReverse = false) { | |
$crc = $initValue; | |
for ($i = 0; $i < strlen($str); $i++) { | |
if ($inputReverse) { | |
// 输入数据每个字节按比特位逆转 | |
$c = ord(reverseChar($str{$i})); | |
} else { | |
$c = ord($str{$i}); | |
} | |
$crc ^= ($c << 8); | |
for ($j = 0; $j < 8; ++$j) { | |
if ($crc & 0x8000) { | |
$crc = (($crc << 1) & 0xffff) ^ $polynomial; | |
} else { | |
$crc = ($crc << 1) & 0xffff; | |
} | |
} | |
} | |
if ($outputReverse) { | |
// 把低地址存低位,即采用小端法将整数转换为字符串 | |
$ret = pack('cc', $crc & 0xff, ($crc >> 8) & 0xff); | |
// 输出结果按比特位逆转整个字符串 | |
$ret = reverseString($ret); | |
// 再把结果按小端法重新转换成整数 | |
$arr = unpack('vshort', $ret); | |
$crc = $arr['short']; | |
} | |
return $crc ^ $xOrValue; | |
} | |
//校验值为 DA4E | |
$string="013836333731363034333737383232313001040000003C020400000708030F3138302E3130312E3134372E3131350404353638330602000007020000080200000901000A04010000150B04010301010C104F4B0D0A002020556E73C90F000064300D0563746E6574"; | |
printf("%x\n", crc16(pack('H*',$string), 0x1021, 0xffff, 0, false, false));//print da4e 通过校验 | |
//这里采用的是 CRC-16/CCITT-FALSE | |
//所有的校验方式如下 | |
/* 列举一些常用的crc16算法 注意如果字符串为16进制请使用pack('H*',string)进行打包 */ | |
// CRC-16/IBM | |
printf("%x\n", crc16('1234567890', 0x8005, 0, 0, true, true)); | |
// CRC-16/MAXIM | |
printf("%x\n", crc16('1234567890', 0x8005, 0, 0xffff, true, true)); | |
// CRC-16/USB | |
printf("%x\n", crc16('1234567890', 0x8005, 0xffff, 0xffff, true, true)); | |
// CRC-16/MODBUS | |
printf("%x\n", crc16('1234567890', 0x8005, 0xffff, 0, true, true)); | |
// CRC-16/CCITT | |
printf("%x\n", crc16('1234567890', 0x1021, 0, 0, true, true)); | |
// CRC-16/CCITT-FALSE | |
printf("%x\n", crc16('1234567890', 0x1021, 0xffff, 0, false, false)); | |
// CRC-16/X25 | |
printf("%x\n", crc16('1234567890', 0x1021, 0xffff, 0xffff, true, true)); | |
// CRC-16/XMODEM | |
printf("%x\n", crc16('1234567890', 0x1021, 0, 0, false, false)); | |
// CRC-16/DNP | |
printf("%x\n", crc16('1234567890', 0x3d65, 0, 0xffff, true, true)); | |
?> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment