将 C CRC16 转换为 Java CRC16

Posted

技术标签:

【中文标题】将 C CRC16 转换为 Java CRC16【英文标题】:Convert C CRC16 to Java CRC16 【发布时间】:2012-10-23 22:42:44 【问题描述】:

我目前正在做一个项目,有一个嵌入式系统通过无线电将数据发送到 PC。数据包最后得到一个 crc16 校验和,它是根据这个算法计算出来的:

uint16_t crc16 (const uint8_t * buffer, uint32_t size) 
    uint16_t crc = 0xFFFF;

    if (buffer && size)
        while (size--)
        
            crc = (crc >> 8) | (crc << 8);
            crc ^= *buffer++;
            crc ^= ((unsigned char) crc) >> 4;
            crc ^= crc << 12;
            crc ^= (crc & 0xFF) << 5;
        

    return crc;

现在我正在寻找 Java 中的等价物。我已经在这里找到了一个不错的: http://introcs.cs.princeton.edu/java/51data/CRC16CCITT.java.html

public class CRC16CCITT  

    public static void main(String[] args)  
        int crc = 0xFFFF;          // initial value
        int polynomial = 0x1021;   // 0001 0000 0010 0001  (0, 5, 12) 

        // byte[] testBytes = "123456789".getBytes("ASCII");

        byte[] bytes = args[0].getBytes();

        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;
        System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
    


但这不适用于我的 C 代码。

是否有人能够为 C 和 Java 等效算法提供适应或解决方案? 谢谢!

【问题讨论】:

为什么要在每次迭代中设置crc = ,因为这与忽略除最后一个值之外的所有值相同。 那我要写什么呢? CRC ^= ?我刚刚从一个开源项目中复制了代码。 有比这更快的计算 CRcs 的方法。不停寻找。有一种表驱动的方法。 OP中的链接已经失效,这里是更新的链接:http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java.html 【参考方案1】:

在这种情况下,java 和 c 之间的主要区别在于,在 c 中您使用无符号数,而 java 只有有符号数。虽然您可以使用带符号的数字实现相同的算法,但您必须意识到符号位在移位操作中被传递,需要一个额外的“与”。

这是我的实现:

static int crc16(final byte[] buffer) 
    int crc = 0xFFFF;

    for (int j = 0; j < buffer.length ; j++) 
        crc = ((crc  >>> 8) | (crc  << 8) )& 0xffff;
        crc ^= (buffer[j] & 0xff);//byte to int, trunc sign
        crc ^= ((crc & 0xff) >> 4);
        crc ^= (crc << 12) & 0xffff;
        crc ^= ((crc & 0xFF) << 5) & 0xffff;
    
    crc &= 0xffff;
    return crc;


【讨论】:

这是我在代码中使用的 CRC 函数 - 只要初始值相同 (0xFFFF) 且多项式相同 (0x1021),它们应该给出完全相同的结果。 我得到的包是:1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 125 -7。 21 字节。包的 crc 为 -1667。我不得不将最后一个的顺序更改为字节。当我使用你的算法时,crc 给我 3377。 你应该传递给我的函数的数据是没有最后两个字节的缓冲区。您可以将我的函数更改为 for (int i = 0; i 这是它目前的样子: byte[] bx = new byte[packet.length - 2]; for(int i = 0; i 我看到我忘了计算c端的crc。但它仍然无法正常工作。包装内容为:1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 51 -100。 c crc 是 13212,java crc 是你的函数 3377。

以上是关于将 C CRC16 转换为 Java CRC16的主要内容,如果未能解决你的问题,请参考以下文章

请将CRC16的C语言算法,改造为JAVA语言算法,万分感谢!

CRC16算法之二:CRC16-CCITT-XMODEM算法的java实现

CRC16算法之一:CRC16-CCITT-FALSE算法的java实现

CRC16算法之三:CRC16-CCITT-MODBUS算法的java实现

javaScript中十六进制转浮点字符串转为ArrayBuffer对象ArrayBuffer转16进度字符串16进制转10进制crc校验位十六进制转包含中文的字符串(包含小程序和浏览器)

CRC校验的实现(C语言,CRC16)