java - Java中的CRC16 DNP校验和算法

标签 java unsigned crc

我一直在尝试从这个实现(从受限制的设备)翻译 CRC16 DNP,但没有任何运气。

uint16_t Crc16Dnp_computeBuffer(uint8_t const (* const message), uint16_t const ui16Size){
uint16_t remainder = INITIAL_REMAINDER;
uint16_t data;
uint8_t byte;

// assert_panic message != 0U

/*
 * Divide the message by the polynomial, a byte at a time.
 */
for (byte = 0; byte < ui16Size; ++byte) {
    data = reflect_byte(message[byte]) ^ (remainder >> (16U - 8U));
    remainder = crcTable[data] ^ (remainder << 8U);
}

/*
 * The final remainder is the CRC.
 */
return (reflect_word(remainder) ^ FINAL_XOR_VALUE);
}

预先计算的表和常量:

  static const uint16_t crcTable[256] = 
{    0x0000, 0x3D65, 0x7ACA, 0x47AF, 0xF594, 0xC8F1, 0x8F5E, 0xB23B, 0xD64D,      0xEB28, 0xAC87, 0x91E2, 0x23D9, 0x1EBC, 
0x5913, 0x6476, 0x91FF, 0xAC9A, 0xEB35, 0xD650, 0x646B, 0x590E, 0x1EA1, 0x23C4, 0x47B2, 0x7AD7, 0x3D78, 0x001D, 
0xB226, 0x8F43, 0xC8EC, 0xF589, 0x1E9B, 0x23FE, 0x6451, 0x5934, 0xEB0F, 0xD66A, 0x91C5, 0xACA0, 0xC8D6, 0xF5B3, 
0xB21C, 0x8F79, 0x3D42, 0x0027, 0x4788, 0x7AED, 0x8F64, 0xB201, 0xF5AE, 0xC8CB, 0x7AF0, 0x4795, 0x003A, 0x3D5F, 
0x5929, 0x644C, 0x23E3, 0x1E86, 0xACBD, 0x91D8, 0xD677, 0xEB12, 0x3D36, 0x0053, 0x47FC, 0x7A99, 0xC8A2, 0xF5C7, 
0xB268, 0x8F0D, 0xEB7B, 0xD61E, 0x91B1, 0xACD4, 0x1EEF, 0x238A, 0x6425, 0x5940, 0xACC9, 0x91AC, 0xD603, 0xEB66, 
0x595D, 0x6438, 0x2397, 0x1EF2, 0x7A84, 0x47E1, 0x004E, 0x3D2B, 0x8F10, 0xB275, 0xF5DA, 0xC8BF, 0x23AD, 0x1EC8, 
0x5967, 0x6402, 0xD639, 0xEB5C, 0xACF3, 0x9196, 0xF5E0, 0xC885, 0x8F2A, 0xB24F, 0x0074, 0x3D11, 0x7ABE, 0x47DB, 
0xB252, 0x8F37, 0xC898, 0xF5FD, 0x47C6, 0x7AA3, 0x3D0C, 0x0069, 0x641F, 0x597A, 0x1ED5, 0x23B0, 0x918B, 0xACEE, 
0xEB41, 0xD624, 0x7A6C, 0x4709, 0x00A6, 0x3DC3, 0x8FF8, 0xB29D, 0xF532, 0xC857, 0xAC21, 0x9144, 0xD6EB, 0xEB8E, 
0x59B5, 0x64D0, 0x237F, 0x1E1A, 0xEB93, 0xD6F6, 0x9159, 0xAC3C, 0x1E07, 0x2362, 0x64CD, 0x59A8, 0x3DDE, 0x00BB, 
0x4714, 0x7A71, 0xC84A, 0xF52F, 0xB280, 0x8FE5, 0x64F7, 0x5992, 0x1E3D, 0x2358, 0x9163, 0xAC06, 0xEBA9, 0xD6CC, 
0xB2BA, 0x8FDF, 0xC870, 0xF515, 0x472E, 0x7A4B, 0x3DE4, 0x0081, 0xF508, 0xC86D, 0x8FC2, 0xB2A7, 0x009C, 0x3DF9, 
0x7A56, 0x4733, 0x2345, 0x1E20, 0x598F, 0x64EA, 0xD6D1, 0xEBB4, 0xAC1B, 0x917E, 0x475A, 0x7A3F, 0x3D90, 0x00F5, 
0xB2CE, 0x8FAB, 0xC804, 0xF561, 0x9117, 0xAC72, 0xEBDD, 0xD6B8, 0x6483, 0x59E6, 0x1E49, 0x232C, 0xD6A5, 0xEBC0, 
0xAC6F, 0x910A, 0x2331, 0x1E54, 0x59FB, 0x649E, 0x00E8, 0x3D8D, 0x7A22, 0x4747, 0xF57C, 0xC819, 0x8FB6, 0xB2D3, 
0x59C1, 0x64A4, 0x230B, 0x1E6E, 0xAC55, 0x9130, 0xD69F, 0xEBFA, 0x8F8C, 0xB2E9, 0xF546, 0xC823, 0x7A18, 0x477D,
0x00D2, 0x3DB7, 0xC83E, 0xF55B, 0xB2F4, 0x8F91, 0x3DAA, 0x00CF, 0x4760, 0x7A05, 0x1E73, 0x2316, 0x64B9, 0x59DC, 
0xEBE7, 0xD682, 0x912D, 0xAC48
};

#define POLYNOMIAL          (uint16_t)0x13D65U
#define INITIAL_REMAINDER   (uint16_t)0x0000U
#define FINAL_XOR_VALUE     (uint16_t)0xFFFFU

在这种情况下,reflect_xx 方法返回数据而不执行任何操作。 我一直在尝试翻译这个,但遇到了 Java 未签名问题...... 我当前的代码:

 public static short crc16dnpComputeBuffer_U(byte[] buf) {
    int remainder = 0x0000;
    int data;
    /*
 * Divide the message by the polynomial, a byte at a time.
     */
    for (int i = 0; i < buf.length; i++) {
        data = (buf[i] ^ (remainder) >>> ((16) - (8))) & 0xffff;
        System.out.println(data);
        remainder = crcTable[data] ^ (remainder << 8) & 0xffff;
    }
    /*
 * The final remainder is the CRC.
     */
    return (short) (remainder ^ (short) 0xFFFF);
}

使用这种方法,数据索引会高于数组长度。

作为此十六进制表示的字节数据的示例:

08AA0001B6340020040B1B1DE5000000000000000000287D0100000000003A7D0100000000003D7D010000000000437D0100000000002E7D0100000000003F7D010000000000367D0100000000003C7D0100000000003E7D0100000000002B7D0100000000003B7D010000000000397D010000000000427D010000000000357D0100000000003F7D010000000000317D0100000000003C7D010000000000387D010000000000467D010000000000

crc 是 E44B

关于我做错了什么有任何提示吗?

谢谢!

更新:在你的帮助下我终于得到了它:

public static short crc16dnpComputeBuffer_U(byte[] buf) {
    int remainder = 0x0000;
    int data;
    /*
 * Divide the message by the polynomial, a byte at a time.
     */
    for (int i = 0; i < buf.length; i++) {
        data = (buf[i] ^ remainder >>> (16) - (8)) & 0xff;
        remainder = crcTable[data] ^ (remainder << 8);
    }
    /*
 * The final remainder is the CRC.
     */
    return (short) (remainder ^ (short) 0xFFFF);
}

最佳答案

shortbyte 在 Java 中被符号扩展为 int,因为所有内容都是有符号的。您需要& 0xff data 的表达式来获取 0..255 范围内的值。 (那么就不需要内部 & 0xfff 了。)

另请注意,您的返回值大约有一半的时间为负值,但这实际上与 C 实现作为正无符号值返回的 16 位值相同。

关于java - Java中的CRC16 DNP校验和算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39242300/

相关文章:

java - 生成高于特定值的 ID

java - 单击按钮将数据从同一页面中的edittext传递到textview

iphone - 如何从 int 转换为无符号短整型 - iPhone

crc - 如何从多项式生成 16 位 CRC 表

java - 为 JPanels 创建垂直滚动面板

Java : Selection Sort Logic

c++ - 为什么 C++ 将 unsigned char 值打印为负数?

将 unsigned char * 转换为 char * string C

crc - 为什么 LevelDB 和 RocksDB 需要 `masked CRC32`

java - 在Java中计算CRC8-Maxim校验和