简介

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

计算流程

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

    实现代码:

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

    实现代码:

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

    实现代码:

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

    实现代码:

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

    实现代码:

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

    实现代码:

    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;
    		}
    	}
    }
    
  7. 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高低字节进行交换

    实现代码:

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

    实现代码:

    return $crc;
    

完整代码

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

功能调用

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

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

参考文章

总结

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