GreenGodot GreenGodot - 3 months ago 47
Java Question

Getting the CRC checksum of a byte array and adding it to that byte array

I have this byte array:

static byte[] buf = new byte[] { (byte) 0x01, (byte) 0x04, (byte)0x00, (byte)0x01,(byte)0x00, (byte) 0x01};


Now, the CRC checksum of this byte array is supposed to be 0x60, 0x0A. I want the Java code to recreate this checksum, however I cant seem to recreate it. I have tried crc16:

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;

}


and convert them using Integer.toHexString(), but none of the results match the correct CRC. Could someone please point me in the right direction in terms of CRC formula.

Answer

Use the following code instead:

// Compute the MODBUS RTU CRC
private static int ModRTU_CRC(byte[] buf, int len)
{
  int crc = 0xFFFF;

  for (int pos = 0; pos < len; pos++) {
    crc ^= (int)buf[pos] & 0xFF;   // XOR byte into least sig. byte of crc

    for (int i = 8; i != 0; i--) {    // Loop over each bit
      if ((crc & 0x0001) != 0) {      // If the LSB is set
        crc >>= 1;                    // Shift right and XOR 0xA001
        crc ^= 0xA001;
      }
      else                            // Else LSB is not set
        crc >>= 1;                    // Just shift right
    }
  }
// Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
return crc;  
}

You may have to reverse your return CRC to get the right endianness, though. I even tested it here:

http://ideone.com/PrBXVh

Using windows calculator or something you can see that the first result (from the above function call) gives the expected value (albeit reversed).