CRC-16-CCITT erzeugen



  • Hallo,

    ich muss eine CRC-16-CCITT-Prüfsumme erstellen. Dazu hatte ich folgenden Code verwendet:

    unsigned short int TcCommand::Crc16Ccitt(char* p_acData, unsigned int uiLength)
    {
      unsigned int uiCrcCheckSum;
      unsigned int uiTemp;
    
      uiCrcCheckSum = 0xFFFF;
      while (uiLength != 0)
      {
        uiTemp = (*p_acData++ << 8);
    
        for (unsigned char cCounter = 0; cCounter < 8; cCounter++)
        {
          if ((uiCrcCheckSum ^ uiTemp) & 0x8000)
            uiCrcCheckSum = (uiCrcCheckSum << 1) ^ 0x8408; // maybe 0x1021 is needed
          else
            uiCrcCheckSum <<= 1;
    
          uiTemp <<= 1;
        }
        uiLength--;
    
      }
      return uiCrcCheckSum;
    }
    

    Allerdings scheint die resultierende Prüfsumme nicht zu stimmen. Kann mir jemand sagen, wo der Fehler liegt?

    Danke!

    Gruß

    Ryo



  • Nimm dir einen Zettel, Stift und rechne jeden Schritt einzeln durch. Falls irgendein Schritt vom erwartenden Ergebnis abweicht hast du den Fehler.



  • Rechne ein Beispiel, lass dir Zwischenergebnisse ausgeben und vergleich sie...





  • Hab den Fehler gefunden. Das Zielsystem ist Big Endian, daher war an meiner Berechnung nichts falsch, es hatte nur einen Bytedreher.



  • Ob das Zielsystem "Big-Endian" ist oder Peng ... Die Funktion ist schlicht und einfach falsch. Es sei denn, Du willst etwas anderes Berechnen als eine CRC-16-CCITT Prüfsumme.

    Zeile 19 ist nicht portabel. char kann vorzeichenbehaftet sein und das Shiften bei negativen Zahlen ist nicht definiert oder implementierungsabhängig.

    Zeile 14 ist falsch. Wenn Du das Register nach links schiebst ("<<1") und das oberste Bit prüfst (&0x8000), dann ist die Konstante 0x8408 falsch. Es muss 0x1021 heißen. Da hat jemand nicht aufgepasst. Wahrscheinlich einfach einen anderen CRC Code auf CRC-16-CCITT "angepasst" und dabei die falsche Konstante eingesetzt. Immerhin hat dieser jemand noch seine Unsicherheit in einem Kommentar verewigt. Leider falsch geraten; denn das, was dabei rauskommt ist viel schlechter als CRC-16-CCITT.



  • Der Kommentar ist von mir.

    Ich hatte den Wert 0x1021 als erstes auch verwendet, allerdings war dann das Ergebnis falsch. Deswegen hatte ich es dann mit 0x8408 probiert.

    Habe es nun aber vorher wieder mit 0x1021 probiert und dabei bemerkt, dass es ja nur falsch ist, weil eben z. B. nicht 0x42CF da steht sondern 0xCF42. Und ja, das hat was mit Big Endian und Little Endian zu tun, ob du das nun glaubst oder nicht.

    Sowsa kommt nunmal vor, wenn man Dateien erzeugt, die von einem Little Endian System kommen und von einem Big Endian System verarbeitet werden.

    Bis auf Zeile 14 ist also alles richtig, also tu mal nicht so, als ob mein Code totaler Mist wäre. Ob etwas compilerabhängig ist oder nicht interessiert mich auch nicht, da bei uns rein mit dem Compiler von Visual Studio gearbeitet wird. Ich hab nie erwähnt, dass mein Code ANSII C++ sein muss. Dass immer direkt alle davon ausgehen.

    Und was du an meiner Zeile 19 auszusetzen hast, versteh ich nicht. Eine geschweifte Klammer sollte doch bei jedem Compiler das gleiche bedeuten. 😉 (und ja, ich weiß, dass du Zeile 9 gemeint hast...)

    Also mal nicht immer gleich so aggressiv reagieren.



  • RyoShinzo schrieb:

    Habe es nun aber vorher wieder mit 0x1021 probiert und dabei bemerkt, dass es ja nur falsch ist, weil eben z. B. nicht 0x42CF da steht sondern 0xCF42. Und ja, das hat was mit Big Endian und Little Endian zu tun, ob du das nun glaubst oder nicht.

    Endianness spielt bzgl 0x8408 vs 0x1021 keine Rolle. Das und nicht mehr habe ich gesagt.

    RyoShinzo schrieb:

    Sowsa kommt nunmal vor, wenn man Dateien erzeugt, die von einem Little Endian System kommen und von einem Big Endian System verarbeitet werden.

    Das kommt nunmal vor, wenn man keinen portablen Code schreibt.

    RyoShinzo schrieb:

    Bis auf Zeile 14 ist also alles richtig, also tu mal nicht so, als ob mein Code totaler Mist wäre.

    Habe ich nie behauptet, dass es totaler Mist ist.

    RyoShinzo schrieb:

    Ob etwas compilerabhängig ist oder nicht interessiert mich auch nicht,

    *mit-den-Achseln-zuck*
    Du kannst die Information nutzen oder ignorieren. Mir ist das im Endeffekt auch egal.

    RyoShinzo schrieb:

    Und was du an meiner Zeile 19 auszusetzen hast, versteh ich nicht.
    (und ja, ich weiß, dass du Zeile 9 gemeint hast...)

    Tschuldige. Jetzt seh' ich's auch. Ich meinte die 9. Zeile.

    Also mal nicht immer gleich so aggressiv reagieren.

    Du sagtest

    ... daher war an meiner Berechnung nichts falsch ...

    Ich bin jetzt davon ausgeganten, dass Du mit "meiner Berechnung" die 0x8408-benutzende Funktion meinstest und wollte Dich nur auf den Fehler hinweisen.



  • @RyoShinzo:
    Way to go, beschimpf die Leute die dir helfen 👍

    BTW: der Code ist Scheissendreck, sowas macht man über Lookup-Tables. Oder verwende gleich eine fertige Implementierung wie die in der Boost.



  • Was gilt denn bei dir als beschimpfen bitte? 😕

    Aber Leute, denen man hilft, die darf man beschimpfen, oder was ist das für dich, anderer Leute Code als "Scheissendreck" (kommt wirklich sehr professionell) zu bezeichnen? 👎



  • Ja, beschimpfen war Unsinn.

    Ich meinte so Sachen wie

    Bis auf Zeile 14 ist also alles richtig, also tu mal nicht so, als ob mein Code totaler Mist wäre.

    Sowas kommt überhaupt gar nicht gut.
    Allgemein dieser beleidigte Ton, als Reaktion auf einen ganz normalen, hilfreichen Beitrag (den Beitrag von krümelkacker mein ich, nicht meinen).

    Way to go! (<- Zynismus)


Anmelden zum Antworten