将CRC16函数从C转换为JAVA而没有unsigned int的问题

时间:2012-11-23 12:48:24

标签: java c crc16

我必须为固件更新创建CRC16校验和。当我发送此数据(从十六进制字符串转换为字节[])

  

020000810000120000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94

我从控制器

获得CRC16
  

-17514

现在我尝试用Java检查这个,但是我无法获得相同的值。

这是C中的原始函数:

static uint16_t crc16_update(uint16_t crc, uint8_t a)
{
  crc ^= a;
  for (unsigned i = 0; i < 8; ++i) {
    if (crc & 1)
      crc = (crc >> 1) ^ 0xA001;
    else
      crc = (crc >> 1);
  }
  return crc;
}


static uint16_t crc16(const uint8_t *b, size_t l)
{
  uint16_t crc = 0;
  while (l-- > 0)
    crc = crc16_update(crc, *b++);
  return crc;
}

这是我在java中的转换函数:

public static int crc16_update(int crc, int a) {
    crc ^= a;
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = (crc >> 1) ^ 0xA001;
        } else {
            crc = (crc << 1);
        }
    }
    return crc;
}

public static int crc16(byte[] bytes) {
    int crc = 0;
    for (byte b:bytes) {
        crc = crc16_update(crc, b);
    }
    return crc;
}

......但它不起作用。怎么了?

4 个答案:

答案 0 :(得分:1)

public static int crc16_update(int crc, int a) {
    crc ^= a;
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = (crc >> 1) ^ 0xA001;
        } else {
            crc = (crc << 1);

作为mentioned by looper,您在C代码中有>> 1

        }
    }
    return crc;
}

现在换另一个功能:

public static int crc16(byte[] bytes) {
    int crc = 0;
    for (byte b:bytes) {
        crc = crc16_update(crc, b);

crc16_update在Java中使用int作为第二个参数,在C中使用uint8_t。当字节b设置其最高有效/符号位时,值为负数,因此当转换为int作为crc16_update的参数时,符号扩展,因此你得到很多你在C中没有的1位。

您需要屏蔽所有位,但最不重要的是

crc16_update(crc, ((int)b) & 0xFF);

答案 1 :(得分:0)

尝试使用>>>运算符。

在Java中,这是无符号移位运算符,而不是保留符号的>>

另请注意,uint16_t是16位类型,与Java中的short类似。在重写位操作的算法时,尝试使用适当的位长度。

答案 2 :(得分:0)

你的问题不是java中签名的整数,而是使用了错误的数据类型。 int有32位,您使用的算法对类型的数据大小敏感。使用short表示16位,byte表示8位。

如果需要,也可以使用{Anony-Mousse提到的>>>

答案 3 :(得分:0)

我找到了正确的方法。现在它工作了!我认为问题是短期和整数之间的实习转换。

public static int crc16_update(int crc, byte a) {
    crc ^= ((a+128) & 0xff);
    for (int i = 0; i < 8; ++i) {
        if ((crc & 1) != 0) {
            crc = ((crc >>> 1) ^ 0xA001) & 0xffff;
        }
        else {
            crc = (crc >>> 1) & 0xffff;
        }
    }
    return crc;
}

public static short crc16(byte[] bytes) {
    int crc = 0;
    for (byte b : bytes) {
        crc = crc16_update(crc, b);
    }
    return (short) crc;
}