2012-11-03 13 views
7

Ich arbeite derzeit an einem Projekt, ein eingebettetes System sendet Daten an einen PC per Funk. Die Pakete erhalten eine CRC16-Prüfsumme am Ende und es auf diesem Algorithmus berechnet basiert:Convert C CRC16 zu Java 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; 
} 

Jetzt habe ich für ein Äquivalent in Java suchen. Ich fand schon ein gutes hier: 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)); 
    } 

} 

Aber dieses arbeitet nicht mit meinem C-Code.

Kann jemand eine Anpassung oder Lösung für einen C- und Java-äquivalenten Algorithmus liefern? Vielen Dank!

+0

Warum setzen Sie 'crc =' bei jeder Iteration, da dies das gleiche ist, jeden Wert als zu ignorieren, aber die letzte. –

+0

Also was muss ich dann schreiben? crc^=? Ich habe den Code von einem Open-Source-Projekt kopiert, mit dem ich gearbeitet habe. – tellob

+0

Es gibt viel schnellere Möglichkeiten CRcs zu berechnen als dies. Suche weiter. Es gibt eine tabellengesteuerte Methode. – EJP

Antwort

21

Der Hauptunterschied zwischen Java und c in diesem Fall ist die Tatsache in c Sie verwenden vorzeichenlose Zahlen und Java hat nur Zahlen signiert. Während Sie den gleichen Algorithmus mit vorzeichenbehafteten Zahlen implementieren können, müssen Sie sich der Tatsache bewusst sein, dass das Vorzeichen-Bit bei Schichtoperationen übernommen wird, was ein zusätzliches "und" erfordert.

Dies ist meine Implementierung:

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; 

} 
+0

Ist das die Implementierung zum c-Code, den ich gepostet habe? – tellob

+0

Dies ist die CRC-Funktion, die ich in meinem Code verwende - vorausgesetzt, der Anfangswert ist der gleiche (0xFFFF) und das Polynom ist das gleiche (0x1021) sie sollten das exakt gleiche Ergebnis geben. – thedayofcondor

+0

Das Paket, das ich bekomme, ist: 1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 125 -7. 21 Bytes. Das Paket crc ist dann -1667. Ich musste die Reihenfolge des letzten Byte ändern. Wenn ich Ihren Algorithmus verwende, liefert crc mir 3377. – tellob