简介

Cyclic Redundancy Check循环冗余检验,是基于数据计算一组效验码,用于核对数据传输过程中是否被更改或传输错误。

计算流程

  1. 预置1个16位的寄存器为十六进制0xFFFF;称此寄存器为CRC寄存器

    实现代码:

1
$crc = 0xFFFF;
  1. 把第一个8位二进制数据(即通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,结果放入CRC寄存器中

    实现代码:

1
$crc=($crc>>8) ^ ord($str[$i]);
  1. 把CRC寄存器的内容右移一位(朝低位)用0填补,并检查右移后的移除位

    实现代码:

1
($crc & 0x0001) == 0
  1. 如果移出位为0:重复第3步(再次右移一位);如果移出位为1:CRC寄存器与0xA001进行异或

    实现代码:

1
2
3
4
5
6
if (($crc & 0x0001) == 0) {
$crc >>= 1;
} else {
$crc >>= 1;
$crc ^= 0xa001;
}
  1. 重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理

    实现代码:

1
2
3
4
5
6
7
8
for($j=0;$j<8;++$j){
if(($crc & 0x0001) == 0){
$crc >>= 1;
}else{
$crc >>= 1;
$crc ^= 0xa001;
}
}
  1. 重复步骤2到步骤5,进行通讯信息帧下一个字节的处理

    实现代码:

1
2
3
4
5
6
7
8
9
10
11
for($i=0;$i<strlen($str);$i++){
$crc=($crc>>8) ^ ord($str[$i]);
for($j=0;$j<8;++$j){
if(($crc & 0x0001) == 0){
$crc >>= 1;
}else{
$crc >>= 1;
$crc ^= 0xa001;
}
}
}
  1. 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高低字节进行交换

    实现代码:

1
$crc = (($crc & 0xff) << 8) | (($crc >> 8) & 0xff);
  1. 最后得到的CRC寄存器内容即为CRC码,将其返回

    实现代码:

1
return $crc;

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function crc16($str){
$crc = 0xffff;
for($i=0;$i<strlen($str);$i++){
$crc=($crc>>8) ^ ord($str[$i]);
for($j=0;$j<8;++$j){
if(($crc & 0x0001) == 0){
$crc >>= 1;
}else{
$crc >>= 1;
$crc ^= 0xa001;
}
}
}
$crc = (($crc & 0xff) << 8) | (($crc >> 8) & 0xff);
return $crc;
}

功能调用

1
2
3
$content = "Hello World!";
$result = crc16($content);
echo $result;

完成后,运行输出结果为481

参考文章

总结

这篇教程到这里就结束了,感谢耐心阅读,如果有问题欢迎在评论区留言。