【问题标题】:Need help in correcting issues in CRC-ITU check method written in java需要帮助纠正用 java 编写的 CRC-ITU 检查方法中的问题
【发布时间】:2014-09-17 11:23:24
【问题描述】:

我们正在尝试在 Java 上编写 GPS 设备侦听器。

在执行此操作时,我们无法为 CRC-ITU 错误检查开发正确的代码。从协议文档生成crc代码的解释如下

终端或服务器可以使用校验码来区分接收到的信息是否有误。为防止数据传输过程中发生错误,在数据误操作的基础上增加了错误校验,提高了系统的安全性和效率。校验码由CRC-ITU校验方法生成。协议结构中数据的校验码,从数据包长度到信息序列号(包括“数据包长度”和“信息序列号”)都是CRC-ITU的值。如果在计算接收到的信息时发生CRC错误,接收方将忽略并丢弃该数据包。

这是数据监听类

      byte[] data = new byte[20];
   System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
                    Socket server = serverSocket.accept();
                    System.out.println("Just connected to " + server.getRemoteSocketAddress());
                    DataInputStream in = new DataInputStream(server.getInputStream());
                    System.out.println("in = " + in);
                    int packetSize = in.read(data, 0, data.length);
                    StringBuilder sb1 = new StringBuilder();
                    for (byte b : data) {
                        sb1.append(String.format("%02X ", b));
                    }
                    System.out.println("loginpacketHex = " + sb1.toString());
                    for (byte b : data) {
                        System.out.println("loginpacketinbytes = " + b);
                    }
                    NewClass cl = new NewClass();
                    byte[] t = new byte[4];
                    byte[] f = new byte[10];
                    t[0] = 0x05;
                    t[1] = data[3];
                    System.out.println(" t[1] = " + t[1]);
                    t[2] = data[data[2] - 6 + 5];
                    System.out.println("t[2] = " + t[2]);
                    t[3] = data[data[2] - 5 + 5];
                    System.out.println("t[3] = " + t[3]);
                    cl.set(t);
                    short x = cl.get();
                    f[0] = 0x78;
                    f[1] = 0x78;
                    f[2] = 0x05;
                    f[3] = data[3];
                    f[4] = data[data[2] - 6 + 5];
                    f[5] = data[data[2] - 5 + 5];
                    f[6] = (byte) ((x >> 8) & 0xff);
                    f[7] = (byte) (x & 0xff);
                    f[8] = 0x0d;
                    f[9] = 0x0a;

这是Crc生成类

public class NewClass {

    public static int crc;

    public static int[] table = {
        0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
        0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
        0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
        0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
        0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
        0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
        0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
        0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
        0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
        0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
        0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
        0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
        0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
        0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
        0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
        0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
        0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
        0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
        0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
        0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
        0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
        0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
        0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
        0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
        0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
        0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
        0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
        0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
        0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
        0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
        0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
        0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,};

    public short get() {
        short c;
        int y;
        y = ~crc;
        c = (short) y;
        return c;
    }

    public void set(byte[] bytes) {
        crc = 0xffff;
        for (byte b : bytes) {
            crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
        }
    }

}

Incoming data string comes in following format

    Example of data packet sent by the terminal 78 78 0D 01 01 23 45 67 89 01 23 45 00 01 8C DD 0D 0A

    Explanation

    Start Bit - 0x78 0x78
    Length - 0x0D
    Protocol - 0x01
    Terminal ID - 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45
    Serial No - 0x00 0x01
    Error - 0x8C 0xDD
    Stop Bit - 0x0D 0x0A

我正在这样做更新代码。

ByteArrayOutputStream bytearrypacket = new ByteArrayOutputStream();
        DataOutputStream responce = new DataOutputStream(bytearrypacket);
        responce.writeByte(0x0D);
        responce.writeByte(1);
        responce.writeByte(0x03);
        responce.writeByte(0x53);
        responce.writeByte(0x49);
        responce.writeByte(0x20);
        responce.writeByte(0x49);
        responce.writeByte(0x00);
        responce.writeByte(0x05);
        responce.writeByte(0x34);
        responce.writeShort(2);
        NewClass cl = new NewClass();
        cl.set(bytearrypacket.toByteArray());
        System.out.println("cl = " + cl.get());
        System.out.println("hexhexhex = " + Integer.toHexString(cl.get()));
        responce.writeShort(cl.get());

        byte[] res = bytearrypacket.toByteArray();
        for (byte b : res) {
            System.out.println("b = " + b);
        }

【问题讨论】:

  • CRC 计算工作正常。你遇到了什么问题?
  • 该数据包中的 CRC,D9 DC,是正确的。你的问题在别处。
  • 我计算了05 01 00 01的CRC-16 ITU,它是D9DC。所以包校验值是正确的。
  • 名为“NewClass”的类的get() 方法返回一个short,它是16 位的。因此它不能是ffffd9dc。只能是d9dc。如果您将short d9dc 分配给int,您将获得ffffd9dc。符号将被扩展(因为 Java 只有有符号整数),给你一个 intffffd9dc。您可以使用 & 0xffff 摆脱符号扩展。或者您可以将其存储在 short 中,因为它首先提供。
  • 将符号扩展名单独留在int 中也可以,因为可以使用(value >> 8) & 0xffvalue & 0xff 访问字节,就像问题中的代码一样,这也去掉了符号扩展位。

标签: java crc16


【解决方案1】:

这是计算CRC的代码

公共类 CRCITUUtil {

private static int[] crcItuTable = {
    0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,
    0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,
    0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,
    0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,
    0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,
    0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,
    0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,
    0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,
    0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,
    0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,
    0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
    0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,
    0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,
    0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,
    0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,
    0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,
    0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,
    0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,
    0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,
    0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,
    0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,
    0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
    0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,
    0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,
    0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,
    0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,
    0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,
    0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,
    0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,
    0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,
    0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,
    0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,
};

public static byte[] getByteArrayFromInt(int value) {
    byte[] result = new byte[4];
    result[0] = (byte) (value >>> 24);
    result[1] = (byte) (value >>> 16);
    result[2] = (byte) (value >>> 8);
    result[3] = (byte) value;
    return result;
}

public static byte[] getCRCITU(byte[] data) {
    int crc = 0xffff;
    for (byte b : data) {
        crc = (crc >>> 8) ^ crcItuTable[(crc ^ b) & 0xff];
    }
    crc = ~crc;
    return getByteArrayFromInt(crc);
}
public static void main(String[] args) {
    byte[] bytes = CRCITUUtil
            .getCRCITU(new byte[] {0x0D, 0x01, 0x01, 0x23, 0x45, 0x67, (byte) 0x89, 0x01, 0x23, 0x45, 0x00, 0x01});
    System.out.println("CRCUIT:"+ Integer.toHexString(0xff & bytes[2]) + " " +  Integer.toHexString(0xff & bytes[3]));
}

}

这将打印出来

CRCUIT:8c dd

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多