Forum: Mikrocontroller und Digitale Elektronik CRC32 Berechnung funktioniert nicht


von Andre (parallax)


Lesenswert?

Hallo,

ich versuche grade auf einer SPS eine CRC32 Funktion zu schreiben, da 
die SPS Libs nur einen CRC 16 hergeben.

Mein Code funktioniert zwar grundsätzlich, leider stimmt mein CRC32 
nicht mit den üblichen Verfahren überein.

Ich habe zu Testzwecken mal den String "1234" als Daten hergenommen.
Mein Polynom ist 16#04C11DB7, binär also 1 0000 0100 1100 0001 0001 1101 
1011 0111.

An meine Daten (chars, also 4 Byte) hänge ich 32 Nullen an.

Nun gehe ich her und wende das 33 bit Polynom mit XOR auf die Daten an, 
beginnend mit der ersten 1 in den Daten.
Vom Ergebnis entferne ich die führenden Nullen und fülle mit den 
nächsten Bits aus den Daten auf und mach die nächste XOR Verknüpfung mit 
den neuen Daten.

Im Internet habe ich eine Seite gefunden die für CRC32 die binären 
Operationen Schritt für Schritt anzeigt, mein Programm tut exakt das 
selbe.
Am Ende bleibt ein Rest übrig, der auch exakt dem Wert aus dem 
Internetbeispiel entspricht. Also so scheint schon mal alles richtig zu 
sein.
Allerdings entspricht das Ergebnis nicht dem Wert, was die üblichen 
verdächtigen CRC32 Online-Generatoren ausspucken.
Nun wird ja bei den Generatoren noch ein Inital Value verwendet und 
außerdem sind je nach Verfahren noch Optionen wie "RefIn", "RefOut", 
"XorOut". Damit weiß ich nicht genau wie ich das impelemtieren soll.
Kann mir jemand sagen wo meine Fehler liegen und was ich noch 
implementieren muss um auf das richtige Ergebnis zu kommen?

Grüße,
Andre

von Hmmm (hmmm)


Lesenswert?

Andre schrieb:
> Nun wird ja bei den Generatoren noch ein Inital Value verwendet

Das ist der Startwert Deines CRC-Registers, den Du verwenden musst, 
statt es mit 0 zu initialisieren.

von Andre (parallax)


Lesenswert?

Hm,
also aktuell initialisiere ich das CRC Register gar nicht. Ich mache 
eine XOR Verknüpfung mit den ersten 33 Bit der Daten und dem Polynom, 
beginnend mit der ersten 1 in den Daten (bzw frame)...
Wie schaut eine solche Initialisierung aus? Erst 33 Bit an 1111111..... 
mit dem Polynom XOR verknüpfen und vom Ergebnis dann führende Nullen 
entfernen und mit Datenbits auffüllen oder wie darf ich mir das 
vorstellen?

Grüße,
Andre

von Hmmm (hmmm)


Lesenswert?

Andre schrieb:
> Wie schaut eine solche Initialisierung aus?

https://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung#Berechnung_einer_CRC-Pr%C3%BCfsumme_in_C_und_Pascal_bzw._Delphi

Dort ist es diese Zeile:
1
uint32_t        crc32       = 0;    /* Schieberegister */

von Joachim B. (jar)


Angehängte Dateien:

Lesenswert?

Andre schrieb:
> Hm,
> also aktuell initialisiere ich das CRC Register gar nicht

vielleicht hilft das?
https://stackoverflow.com/questions/2587766/how-is-a-crc32-checksum-calculated

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?


von Andre (parallax)


Lesenswert?

Hallo,
vielen Dank für die Antworten, habs vor Weihnachten noch hingebracht mit 
den Links aus euren Beiträgen.
Da das Thema ja öfter zu finden ist, erkläre ich schnell die 
Vorgehensweise um evtl anderen Usern helfen zu können.

Der CRC32 verfügt standardmäßig über 4 Parameter, welche je nach 
Variante verwendet werden können oder nicht. Das sind:
Initial Value
Reverse Input
Reverse Output
XOR Output Mask

Zuerst werden die Daten, aus welchen der CRC32 berechnet werden soll 
binär umgewandelt. Ist die Option Reverse Input gesetzt, wird jedes Byte 
jedoch verdreht, das heißt BIT0 kommt an Stelle von BIT7, BIT1 kommt an 
Stelle von BIT6, BIT2 an Stelle, von BIT5 und so weiter. Anschließend 
werden an die nun entstandene Bit-Folge 32 Nullen angehangen.
Nun werden die ersten 32 Bit der Daten mit ebenfalls 32 Bit langen 
Initial Value mit XOR verknüpft. Bei einem Initial Value von 16xFFFFFFFF 
würden alle 32 Bits invertiert werden, bei einem Initial Value von 
16x00000000 würden alle 32 Bits so bleiben wie sie sind. Für andere 
Initial Values ergibt sich ein anderes verhalten.

Nun werden von den Daten führende Nullen entfernt, soweit welche 
vorhanden sind.
Anschließend beginnt die Polynomdivision mit dem CRC32 Polynom. Das 
Polynom ist 33 Bit lang und beginnt immer mit einer 1. Auch beim 
Standard Polynom (16x04C11DB7) ist das so, die erste 1 wird nur im 
Polynom nicht geschrieben, da sie standardmäßig immer 1 ist. Es werden 
also nun 33 Bits der Daten mit den 33 Bits des Polynoms mit XOR 
verknüpft. Das Ergebnis hat nun mindestens eine führende Null (Da die 
Daten mit 1 beginnen und auch das Polynom mit 1 beginnt, ergibt das 
erste Bit immer 0).
Die führenden Nullen des Ergebnisses werden nun entfernte und am Ende 
mit den folgenden Bits aus den Datan aufgefüllt. Nun erfolgt die nächste 
XOR Verknüpfung mit dem Polynom. Dabei erhält man mindestens wieder eine 
führende 0. Man verfährt nun so weiter bis man alle Bits der Daten durch 
hat.
Am Ende erhält man den 32 Bit langen CRC32 (das höchste, 33ste Bit ist 
ja wieder Null und kann entfernt werden).

Ist nun noch die Option Reverse Output aktiv werden die kompletten 32 
Bit des CRC32 nochmal umgedreht, also BIT1 an Stelle von BIT32 und so 
weiter.

Zu guter Letzt gibt es noch die XOR Output Mask. Diese ist 32 Bit lang. 
Damit wird nun der CRC32 nochmals XOR verknüpft. Bei einer Output Mask 
von 0xFFFFFFFF würden auch hier wieder alle Bits invertiert werden, bei 
0x00000000 würde das Ergebnis unverändert bleiben, alle anderen Output 
Masks würden natürlich zu einem anderen Verhalten führen.

Ich konnte das so in meiner SPS umsetzten und alle CRC32 mit allen 
möglichen Optionen stimmen mit den Ergebnissen üblicher Online 
Generatoren überein. Ich hoffe ich konnte hier dem ein oder anderen, 
welcher auch in Problem damit hat, weiterhelfen.

Grüße

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.