[英]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.