简体   繁体   English

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

[英]Problems converting CRC16 function from C to JAVA without unsigned int

I have to create a CRC16 checksum for a firmware update. 我必须为固件更新创建CRC16校验和。 When I send this Data (converted from hex-string to byte[]) 当我发送此数据(从十六进制字符串转换为字节[])时

020000810000120000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94 020000810000120000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94

I get following CRC16 from the controller 我从控制器得到CRC16

-17514 -17514

now I try to check this in Java, but I can't get the same value. 现在我尝试用Java检查这个,但我不能得到相同的值。

This are the original functions in C: 这是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;
}

this are my converted functions in java: 这是我在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;
}

... but it doesn't work. ......但它不起作用。 What's wrong with it? 它出什么问题了?

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

As mentioned by looper , you have a >> 1 there in the C code. 正如looper提到的 ,你在C代码中有一个>> 1

        }
    }
    return crc;
}

Now for the other function: 现在换另一个功能:

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

crc16_update takes an int as second argument in Java, a uint8_t in C. When the byte b has its most significant/sign bit set, the value is negative, and thus when converted to int as argument to crc16_update , sign-extended, thus you get a lot of 1-bits that you don't have in C. crc16_update在Java中使用int作为第二个参数,在C中使用uint8_t 。当字节b设置了其最高有效/符号位时,该值为负,因此当转换为int作为crc16_update参数时,符号扩展,因此你得到很多你在C中没有的1位。

You need to mask out all bits but the least significant 8, 你需要屏蔽所有位,但最不重要的是8,

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

Try using the >>> operator. 尝试使用>>>运算符。

In Java, this is the unsigned shift operator, as opposed to >> which preserves the sign. 在Java中,这是无符号移位运算符,而不是保留符号的>>

Also note that uint16_t is a 16 bit type, as is short in Java. 另请注意, uint16_t是16位类型,在Java中很short Try to use the appropriate bit length, when rewriting algorithms that work on a bit level. 当重写在位级上工作的算法时,尝试使用适当的位长度。

You problem is not that integers a signed in java but you use the wrong datatype. 你的问题不是java中签名的整数,而是使用了错误的数据类型。 int has 32 bit and the algorithm you use is sensitive to the datasize of the types. int有32位,您使用的算法对类型的数据大小敏感。 Use short for 16 bit and byte for 8 bit. 使用16位short和8位byte

Also use >>> , where necessary, as mentioned by @Anony-Mousse. 如有必要,也可以使用>>> ,如@ Anony-Mousse所述。

I've found the right way. 我找到了正确的方法。 Now it work's! 现在它工作了! I think the problem was the intern converting between short and int. 我认为问题是短期和整数之间的实习转换。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM