Hallo,
ich bin seit Ewigkeiten auf der Suche nach einer Funktion zur Berechnung
einer CRC32. (grundlegendes Polynom: 0xEDB88320)
Das ganze sollte ohne LookUp-Table gemacht werden, da ich keine
(riesige) Tabelle in dem verwendeten PIC vorhalten kann. (langsamer,
weniger Speicherplatz notwendig)
Zudem sollte die Bildung der Prüfsumme byteweise geschehen.
Für einige sachdienliche Hinweise wäre ich mehr als dankbar.
Vielen Dank.
Guest schrieb:
> ich bin seit Ewigkeiten auf der Suche nach einer Funktion zur Berechnung> einer CRC32. (grundlegendes Polynom: 0xEDB88320)
Ja, man muß da schon einige Sekunden googlen:
http://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung
Peter
Das Beispiel hatte ich mir bereits angesehen...
Was mich daran gestört hat: Es ist immer die Rede von Datenbits?!
int datastream[]={1,0,0,0,1,1,0,0}
bei mir wäre es aber ein char-Array, also ausschließlich Bytewerte
z.B.
int testdata[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
Wenn ich über diese 8Byte (!) jetzt mit zwei unterschiedlichen
Checksum-Tools eine CRC32 mache, komme ich auf die Prüfsumme 0x3fca88c5.
Und die ist auch vollkommen korrekt meiner Ansicht nach.
Mit der Wikipedia-Routine ist mir das aber nicht gelungen.
Kann das jemand vielleicht überprüfen mit dem oben genannten Datenstrom
und dem Polynom 0xEDB88320? (sonst werde ich hier noch wahnsinnig)
Danke sehr. Einen schönen Tag weiterhin.
Guest schrieb:
> Das Beispiel hatte ich mir bereits angesehen...> Was mich daran gestört hat: Es ist immer die Rede von Datenbits?!>> int datastream[]={1,0,0,0,1,1,0,0}
Die 8 Bits sind hier verschwenderisch als int gespeichert, soll ja nur
das Prinzip verdeutlichen.
Dein Problem ist also, wie Du die CRC über 8 Bits eines Bytes macht?
Dazu schiebt man sie einfach der Reihe nach durch:
1
#include<inttypes.h>
2
3
#define CRC32POLY 0x04C11DB7 /* CRC-32 Polynom */
4
5
uint32_tcrc_32(uint32_tcrc32,uint8_tval)
6
{
7
uint8_ti;
8
for(i=8;i;i--){// 8 bits per byte
9
if(((crc32&0x80000000)?1:0)!=(val&1))// test LSB
10
crc32=(crc32<<1)^CRC32POLY;
11
else
12
crc32<<=1;
13
val>>=1;// shift data bits
14
}
15
returncrc32;
16
}
Ich hab jetzt mal LSBit first vermutet (Linksschieben).
Peter
datastream[] ist in meinem Fall wohl mein Char-Buffer also (0x01 bis
0x08) nehme ich stark an.
Für databits habe ich die Anzahl der Elemente meines Buffers angenommen,
also 8. (sozusagen die buffer_length)
Das Ergebnis ist halt nicht richtig. Ich frage mich jetzt, was ICH
falsch mache...
wirkilch ist was du beabsichtigst? Du berechnest den CRC ueber 8 Bytes,
aber die Werte schauen verdaechtig danach aus, dass du den CRC
eigentlich ueber 8 Bits berechnen wolltest...
Habe mir den CRC code nicht genauer angeschaut, aber auf den ersten
Blick sieht er gut aus.
Mit pycrc (http://www.tty1.net/pycrc/) laesst sich gut mit verschiedenen
Parametern und Eingabedaten experimentieren. Und btw, pycrc kann dir
auch C-Code generieren.
Thomas
Ich habe jetzt verstanden was obiger Code macht: er nimmt nur EIN bit
von jedem Byte in deinem datastream. Der Code aus dem Wikipedia Artikel
ist nur fuer didaktische Zwecke geeignet, in einem wirklichen Programm
wirst du die CRC Berechnung so nicht finden.
Hallo
Der Code von Peter Dannegger ist schon sehr gut! Besser geht es kaum
noch
Falls du nicht mit irgendwas kompatibel sein musst, ist ein invertierter
CRC, bei dem du nicht auf & 0x80000000 prüfen musst sondern auf & 0x01
besser, da es vorher einen Cast auf (uint8_t) ermöglicht -> spart
Rechenschritte.
hier mal etwas ungetesteter code (hab grad keinen C Compiler da)
Ich habe den CRC32 in einen Pointer geändert, so kann er bei späteren
Aufrufen wiederverwendet werden. Außerdem funktioniert (sollte) es über
mehrere Bytes.
Nicht vergessen: *crc32 mit 0xFFFFFFFF initialisieren und ganz zum
schluss ein xor mit 0xFFFFFFFF
Es wäre didaktisch besser gewesen, wenn Du geschrieben hättest was genau
Du an der For-Schleife nicht verstehst.
Ich nehme aber an, das Du die Abbruchbedingung meinst die hier lediglich
aus:
1
...;i;...
besteht.
Schau Dir mal die Beschreibung der For-Schleife in einem guten C-Buch
an.
Der Witz ist das zwischen "Wahr" und "Falsch" und Zahlenwerten eine
Beziehung besteht. Wahr ist jeder Wert ungleich 0. Falsch hingegen eben
die verbleibende Null.
Wenn also das oberste Bit immer weiter nach rechts schiebst, wird es
irgendwann rechts aus dem Byte fallen, auf den Tisch fallen und Bing
machen.
Dann ist i = Null, also Falsch. Die Schleife wird beendet.
@Sumynona:
Vielen Dank, jetzt macht die Schleife mehr Sinn. Hab´s verstanden...
@Wiesel:
"Es wäre didaktisch besser gewesen, wenn Du geschrieben hättest was
genau
Du an der For-Schleife nicht verstehst. Ich nehme aber an, das Du die
Abbruchbedingung meinst die hier lediglich aus..."
Die Aussage war der Oberhammer an diesem heutigen Nachmittag. Wenn du
mal höher scrollst dann stand/steht da in etwa folgendes:
"Vor allem die Abbruchbedingung kann ich derzeit nicht deuten..."
Habe in diesem Thread wirklich viel Gutes, nur leider auch ziemlich viel
Blödes lesen müssen.
Hi,
kann mir einer helfen, das Bsp zum laufen zu bekommen?
Ich übergebe val = 0x50;
crc32 = 0xffffffff;
Ergebnis der Funktion ist: 0x61826962
Sämtlich onlinekalkulatoren geben mit diesem Input als Ergebnis
0xB969BE79.
Warum?
Peter D. schrieb:>> #define CRC32POLY 0x04C11DB7 /* CRC-32 Polynom */>> uint32_t crc_32( uint32_t crc32, uint8_t val )> {> uint8_t i;> for(i = 8; i; i--){ // 8 bits per byte> if(((crc32 & 0x80000000) ? 1 : 0) != (val & 1)) // test LSB> crc32=(crc32<<1) ^CRC32POLY;> else> crc32<<=1;> val >>= 1; // shift data bits> }> return crc32;> }>> Ich hab jetzt mal LSBit first vermutet (Linksschieben).>> Peter
Viele Grüße
Jannik
Es gibt 4 verschiedene Problemstellen:
1) der Startwert (0 oder alles ff?)
2) lsb zuerst oder msb zuerst?
3) Dementsprechend das Polynom mal gespiegelt, mal nicht
4) nochmal Invertierung des Endwertes (ja/nein)
CRC ist sehr effizient bei der Verarbeitung einer Bit-Folge. Dabei
spielt es eine Rolle, ob das niederwertigste Byte zuerst kommt oder das
höchstwertige. Dementsprechend kommt auch das niederwertigste Bit zuerst
bzw. das höchwertigste.
Der Erste Link bei Wikipedia liefert Dir sowohl online-Rechner als auch
C-Code.
Bitte angeben, wie genau Du berechnest, der Code zeigt es nicht, die
Initialisierung (und ggf. Finalisierung) fehlen.
Der Rechner kommt in keiner Variation auf keinen Deiner Wert. Womit hast
Du getestet.
Hallo Achim,
danke für deine ausführliche Antwort.
Ich habe Bsp in dem Kalkulator:
https://www.lammertbies.nl/comm/info/crc-calculation.html den Hexwert
0x50 getestet. Dieser benutzt im Ergebnis CRC32 dasselbe Polynom
(0x04C11DB7). Ergebnis hier: 0xB969BE79.
Ich initialisiere mit 0xffffffff, wie bereits oben geschrieben. Versucht
habe ich beide Varianten LSB und MSB first (0x50 und 0x05).
Bei der Polynomspiegelung verlasse ich mich auf die fertige Funktion,
dass es hier nicht not tut und mit LSB/MSB first funktionieren soll. Ein
abschließendes XOR vom Ergebnis ergibt auch keinen gleichen Wert.
Der Code wurde direkt auf einem 32bit Mikrocontroller getestet.