2013-07-04 11 views
7

hinzugefügt habe ich diesen Byte-Array:das CRC-Prüfsumme eines Byte-Array und zu ihm zu diesem Byte-Array

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

Nun werden die CRC-Prüfsumme dieses Byte-Array soll 0x60, 0x0A sein. Ich möchte, dass der Java-Code diese Prüfsumme neu erstellt, aber ich kann es nicht neu erstellen. Ich habe crc16 versucht:

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; 

} 

und wandeln sie mit Integer.toHexString(), aber keines der Ergebnisse entsprechen den richtigen CRC. Könnte mir jemand bitte in Bezug auf die CRC-Formel in die richtige Richtung weisen?

Antwort

10

Verwenden Sie stattdessen den folgenden Code:

// 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; 
} 

Sie haben Ihre Rückkehr CRC umkehren das Recht endianness zu bekommen, though. Getestet habe ich es auch hier:

http://ideone.com/PrBXVh

Windows-Rechner oder etwas verwenden können Sie sehen, dass das erste Ergebnis (aus der obigen Funktionsaufruf) gibt den Erwartungswert (wenn auch umgekehrt).

+0

Ja, es funktioniert, jetzt alles, was ich tun muss, ist es umzukehren. Vielen Dank! – GreenGodot

2

Ich arbeitete an Modbus mit Java 1.6, versuchte den obigen Code und es funktionierte nur teilweise? Vereinbart bei einigen CRCs, falsch bei anderen. Ich recherchierte es ein wenig mehr und sah, dass ich ein Problem mit der Zeichenerweiterung hatte. Ich maskierte die hohen Bits (siehe FIX HIER unten) und jetzt funktioniert es großartig. HINWEIS: Alle CRC calcs sind nicht die gleichen, MODBUS ist ein bisschen anders:

public static int getCRC(byte[] buf, int len) { 
    int crc = 0xFFFF; 
    int val = 0; 

     for (int pos = 0; pos < len; pos++) { 
     crc ^= (int)(0x00ff & buf[pos]); // FIX HERE -- 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, crc has low and high bytes swapped, so use it accordingly (or swap bytes) 
    val = (crc & 0xff) << 8; 
    val = val + ((crc >> 8) & 0xff); 
    System.out.printf("Calculated a CRC of 0x%x, swapped: 0x%x\n", crc, val); 
    return val; 

} // end GetCRC 
2

Would CRC32 tun, oder es muss CRC16 sein? Wenn 32 in Ordnung ist, haben Sie versucht, CRC32 in java.util.zip zu verwenden?

import java.util.zip.CRC32; 

byte[] buf = new byte[] { (byte) 0x01, (byte) 0x04, (byte)0x00, (byte)0x01,(byte)0x00, (byte) 0x01}; 
CRC32 crc32 = new CRC32(); 
crc32.update(buf); 
System.out.printf("%X\n", crc32.getValue()); 

Die Ausgabe lautet:

F9DB8E67 

Dann können Sie tun, was zusätzliche Berechnung Sie obendrein wollen.