硬件对接crc效验

IT球球

截图
有大佬知道这种效验怎么实现吗,找了很多网上代码效验都不正确

980 4 2
4个回答

li914

根据java示例,测试的代码:

public class Demo {
    public static void main(String[] args) {
        byte[] bytes = {1,2,3};
        System.out.println(getCRC(bytes)); // 结果:24881
    }

    public static int getCRC(byte[] bytes)
    {
        int crc = 0x0000;
        int polynomial = 0x1021;
        for (byte b : bytes){
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7-i)&1)==1);
                boolean c15 = ((crc >> 15 &1)==1);
                crc <<=1 ;
                if (c15^bit)crc^=polynomial;
            }
        }
        crc &= 0xffff;
        return crc;
    }
}

然后根据java示例转PHP代码:

function getCRC($arr)
{
    $crc = 0x0000;
    $polynomial = 0x1021;
    foreach ($arr AS $b){
        for ($i=0;$i<8;$i++){
            $bit = (($b>>(7-$i)&1)==1);
            $c15 = (($crc>>15 & 1)==1);
            $crc<<=1;
            if ($c15^$bit)$crc^=$polynomial;
        }
    }
    $crc &= 0xffff;
    return $crc;
}
//$arr1 = array();
//$str1 = '688c02340c32303231303830333130313000a135220531171637';
//$len = mb_strlen($str1);
//for ($j=0;$j<($len/2);$j++){
//    array_push($arr1,hexdec(mb_substr($str1,($j*2),2)));
//}
//echo implode(',',$arr1).PHP_EOL;

$str = '68 8c 02 34 0c 32 30 32 31 30 38 30 33 31 30 31 30 00 a1 35 22 05 31 17 16 37';
$strArr = explode(' ',$str);
$arr = array();
foreach ($strArr AS $value){
    array_push($arr,hexdec($value));
}

echo implode(',',$arr).PHP_EOL;
echo getCRC($arr);

不知道这样子是否正确

  • li914 2022-06-01

    注意: 根据Java示例,数组中的数字,不能大于 127,不能小于 -128

  • IT球球 2022-06-01

    68 8c 02 34 0c 32 30 32 31 30 38 30 33 31 30 31 30 00 a1 35 22 05 31 17 16 37能帮我是试一下这一串看是否一样吗,大佬

  • li914 2022-06-01

    这是16进制的字符串? 要试什么?

  • li914 2022-06-01

    我只是小垃圾一个 不是大佬

  • IT球球 2022-06-01

    他现在就是想把这个16进制用这个方式效验,但是我一直效验不对,你能帮我看看java和php用你这2块代码一样吗

  • li914 2022-06-01

    不是很明白你是要怎么效验

    我拿你给的十六进制字符串,然后转 十进制数字数组 ,java和php返回结果是一样的
    数组:104,140,2,52,12,50,48,50,49,48,56,48,51,49,48,49,48,0,161,53,34,5,49,23,22,55
    结果:39216

  • IT球球 2022-06-01

    谢谢了,我这边在处理一下,这个文档有问题,他们需要CRC-16/XMODEM效验,文档没跟新

  • li914 2022-06-01

    呃呃呃 好吧

  • IT球球 2022-06-01

    能把你那个php 十六进制字符串,然后转 十进制数字数组 最后输出39216那个代码发一下吗兄弟

  • IT球球 2022-06-01

    能把你php 那个 转10进制数组代码给我看看吗

  • li914 2022-06-01

    呃呃呃 只是简单的转换 等一下

  • IT球球 2022-06-01

    找到代码啦,谢谢兄弟了

  • li914 2022-06-01

    已经放到代码里了

  • IT球球 2022-06-01

    感谢

2548a

我按我理解给你翻译了一下,正常来说应该是跟java版一样的
public function getCRC(array $bytes){
$crc = 0x0000;
$polynomial = 0x1021;
foreach ($bytes as $b){
for ($i = 0 ; $i<8;$i++){
$bit = (($b >>(7-$i)& 1 )=== 1);
$c15 = (($crc >>15 &1 ) === 1);
$crc <<=1;
if ($c15^$bit){
$crc^= $polynomial;
}
}
}
$crc &= 0xfff;
return $crc;
}

  • 暂无评论

有个crc16类 你试试能不能用,里面有CRC16的XMODEM校验方法


class Crc16
{
    /**
     * CRC-16/IBM
     * @param $str
     * @return mixed
     */
    public static function IBM($str)
    {
        return self::hash($str, 0x8005, 0, 0, true, true);
    }

    /**
     * CRC-16/MAXIM
     * @param $str
     * @return mixed
     */
    public static function MAXIM($str)
    {
        return self::hash($str, 0x8005, 0, 0xffff, true, true);
    }

    /**
     * CRC-16/USB
     * @param $str
     * @return mixed
     */
    public static function USB($str)
    {
        return self::hash($str, 0x8005, 0xffff, 0xffff, true, true);
    }

    /**
     * CRC-16/MODBUS
     * @param $str
     * @return mixed
     */
    public static function MODBUS($str)
    {
        return self::hash($str, 0x8005, 0xffff, 0, true, true);
    }

    /**
     * CRC-16/CCITT
     * @param $str
     * @return mixed
     */
    public static function CCITT($str)
    {
        return self::hash($str, 0x1021, 0, 0, true, true);
    }

    /**
     * CRC-16/CCITT-FALSE
     * @param $str
     * @return mixed
     */
    public static function CCITT_FALSE($str)
    {
        return self::hash($str, 0x1021, 0xffff, 0, false, false);
    }

    /**
     * CRC-16/X25
     * @param $str
     * @return mixed
     */
    public static function X25($str)
    {
        return self::hash($str, 0x1021, 0xffff, 0xffff, true, true);
    }

    /**
     * CRC-16/XMODEM
     * @param $str
     * @return mixed
     */
    public static function XMODEM($str)
    {
        return self::hash($str, 0x1021, 0, 0, false, false);
    }

    /**
     * CRC-16/DNP
     * @param $str
     * @return mixed
     */
    public static function DNP($str)
    {
        return self::hash($str, 0x3d65, 0, 0xffff, true, true);
    }

    /**
     * 将一个字符按比特位进行反转 eg: 65 (01000001) --> 130(10000010)
     * @param $char
     * @return string $char
     */
    private static 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
     * @return mixed
     */
    private static function reverseString($str)
    {
        $m = 0;
        $n = strlen($str) - 1;
        while ($m <= $n) {
            if ($m == $n) {
                $str[$m] = self::reverseChar($str[$m]);
                break;
            }
            $ord1 = self::reverseChar($str[$m]);
            $ord2 = self::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
     */
    public static function hash($str, $polynomial, $initValue, $xOrValue, 
    $inputReverse = false, $outputReverse = false)
    {
        $crc = $initValue;

        for ($i = 0; $i < strlen($str); $i++) {
            if ($inputReverse) {
                // 输入数据每个字节按比特位逆转
                $c = ord(self::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 = self::reverseString($ret);
            // 再把结果按小端法重新转换成整数
            $arr = unpack('vshort', $ret);
            $crc = $arr['short'];
        }
        return $crc ^ $xOrValue;
    }
}
  • 暂无评论
Gin
private function crc16($string){
        $string = pack('H*', $string);
        $crc = 0xFFFF;
        for ($x = 0; $x < strlen ($string); $x++) {
            $crc = $crc ^ ord($string[$x]);
            for ($y = 0; $y < 8; $y++) {
                if (($crc & 0x0001) == 0x0001) {
                    $crc = (($crc >> 1) ^ 0xA001);
                } else {
                    $crc = $crc >> 1;
                }
            }
        }
        $high8 = str_pad(dechex(floor($crc / 256)), 2, '0', STR_PAD_LEFT);
        $low8 = str_pad(dechex($crc % 256), 2, '0', STR_PAD_LEFT);

       return [strtoupper($high8), strtoupper($low8)];
    }

我项目这样用的,可用

  • 暂无评论
年代过于久远,无法发表回答
🔝