Skip to content

Instantly share code, notes, and snippets.

@hainuo
Last active August 23, 2019 17:30
Show Gist options
  • Save hainuo/d84a084fe899e17e466573c752df29a7 to your computer and use it in GitHub Desktop.
Save hainuo/d84a084fe899e17e466573c752df29a7 to your computer and use it in GitHub Desktop.
php crc16校验值
<?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