CRC16 von Maxim Frage

Gast #2160948
Lesenswert?

Hallo Leute,

ich wollte einen CRC-Generator programmieren, der möglichst schnell ist. 
Dazu gibt es natürlich viele Source-Codes.

Ich habe nun folgenden für das Polynom x^16 + x^15 + x^2 + 1 gefunden:
1
 
2
unsigned int calcCRC(unsigned int srcCRC, unsigned char testByte)
3
{
4
       int i;
5

6
       srcCRC ^= testByte;
7

8
       for (i = 0; i < 8; ++i)
9
       {
10
         if (srcCRC & 1)
11
           srcCRC = (srcCRC >> 1) ^ 0xA001;
12
         else
13
           srcCRC = (srcCRC >> 1);
14
       }
15
       return srcCRC;
16

17

18
  
19
}
20

21
//Aufruf in Main
22
void main ()
23
{
24
 unsigned int CRC;
25

26
 unsigned char byte1=0xAA;
27
 unsigned char byte2=0xAA;
28

29

30
 //Vorladewert
31
 CRC = 0xFFFF;//0x0000;
32

33
 CRC = calcCRC(myCRC, b1);
34

35
 CRC = calcCRC(myCRC, b2);
36
}

Dann bin ich noch auf die folgende Seite gestoßen:

http://www.lammertbies.nl/comm/info/crc-calculation.html?crc=00000003&method=hex


Je nachdem welchen Vorladewert ich eingebe, kommt entweder das Gleiche 
oder was anderes raus.
Meine Frage ist nun, welchen Vorladewert wird für eine CRC16 bei einem 
1-Wire-Produkt verwendet (z.B. EEPROM)?
Benutzt Maxim einen Wert von 0x0000 oder 0xFFFF?

Vielen Dank für eure Hilfe.

Grüße
M.U.
Gast #2161089
Lesenswert?

Hallo M.U.

aus meiner Erinnerung ist in den meisten Fällen 0xffff als startwert für 
die CRC Berechnung zu wählen. 0x0000 ist mir bisher noch nicht 
untergekommen. Aber vieleicht irre ich mich auch

Hoffe Dir geholfen zu haben

Gruß

Detlev
Gast #2161151
Lesenswert?

Hallo Detlev,

danke für die Antwort.

Ich werde es mal mit 0xFFFF testen. Vielleicht funktioniert es ja.
Wenn nicht, muss ich es nochmal mit 0x0000 ausprobieren.

Leider finde ich keine wirklich eindeutige Beschreibung von 
Dallas/Maxim, die den Startwert für die CRC16 beschreibt.


Grüße
M.U.
Gast #2162102
Lesenswert?

@eProfi:

Deine Version ist keine eine-Zeile-Version. Du hast doch nur alle 
Befehle in eine Zeile geschmissen - so würde ja jeder eine 
eine-Zeile-Version schreiben.

Aber du hast die Standardausführung der CRC16-Routine sehr gut 
zusammengefasst, soweit ich das auf die Schnelle beurteilen kann. Dafür 
ein großes Lob an dich!

Euer
Pro-Grammar
Gast #2163483
Lesenswert?

Danke,  hör ich gern.

Die Versionen funktionieren alle und sind äquivalent.

hier habe ich noch drei:
for(i=9;--i;c=c>>1^((c^d)&1?p:0),d>>=1);
for(i=9;--i;c=c/2^((c^d)&1?p:0),d/=2);
for(i=9;--i;d/=2)c=c/2^((c^d)&1?p:0);

Ich glaub, noch kürzer geht es nicht.

Der Vorteil ist, dass das Zero-Flag nach dem --i direkt ausgewertet 
werden kann, was einen Befehl (compare) einspart.
Nachteil ist, dass man wissen muss, dass die Routine nur 8 mal 
durchlaufen wird, trotzdem 9 dortsteht.
Evtl. könnte man i=8+1 schreiben. Aber ich mag es gern kurz.

Der Link zum o.g. 1w-standard (Book of iButton standards):
AN937, AN 937, APP937, Appnote937, Appnote 937
http://pdfserv.maxim-ic.com/en/an/AN937.pdf
Gast #2163655
Lesenswert?

Hi,

ich habe noch eine Frage zu deiner Auswertung mit der for-Schleife:


eProfi schrieb:
> for(i=9;--i;c=c>>1^((c^d)&1?p:0),d>>=1);
> for(i=9;--i;c=c/2^((c^d)&1?p:0),d/=2);



Wie habe ich die zu interpretieren?

Ich meine, klar: i=9 ist der Wert, der initialisiert wird.
Aber käme nicht an zweiter STelle die Bedingung, wie weit gezählt wird 
und an dritter Stelle die Anzahl, um die runtergezählt werden soll.
Aber irgendwie ist das bei dir vertauscht und du hast in der dritten 
Anweisung noch ein "," eingefügt - was hat das zu bedeuten?

Vielen Dank für deine grandiose Hilfe :-)

Grüße
M.U.
(Firma: mayer) Persönliche Seite #2163696
Lesenswert?

hallo Miss Understood

> Wie habe ich die zu interpretieren?
> Aber käme nicht an zweiter STelle die Bedingung, wie weit gezählt wird

ja ist es ja auch.
solange i groesser null ist, wird es ausgefuehrt. zusaetzlich wird halt 
noch davor um 1 hinunter gezaehlt.
eine anweisung  if(i>0)  kann auch als   if(i)  geschrieben werden.
( gilt in diesem fall natuerlich nur fuer positive i's.

gruss
hans

--
Gast #2163727
Lesenswert?

Hans Mayer schrieb:
> ja ist es ja auch.
> solange i groesser null ist, wird es ausgefuehrt. zusaetzlich wird halt
> noch davor um 1 hinunter gezaehlt.
> eine anweisung  if(i>0)  kann auch als   if(i)  geschrieben werden.
> ( gilt in diesem fall natuerlich nur fuer positive i's.

Ok, das habe ich verstanden. Eigentlich auch logisch. Danke.

Aber bei folgendem Ausdruck

c=c>>1^((c^d)&1?p:0),d>>=1

weiß ich nicht was das Komma bedeutet.

Ich hätte den Befehl jetzt mal so übersetzt:
C= Wert, d>>=1

c>>1^((c^d)&1?p:0) <- das ergibt ja irgendeinen Wert. Was allerdings das 
",d>>=1" bedeutet kann ich nicht so richtig interpretieren.

Danke für eure Hilfe.

@Peter:
Dann werde ich mal die CRC wieder einbauen. Danke :-)

Gruß
M.U.
Gast #2164508
Lesenswert?

Ich gebe zu, das sind schon fortgeschrittenen Tricks.

> for(i=9;--i;

Er erwartet als zweiten Parameter einen Wert, der mit Null verglichen 
wird.
--i ist dann Null, wenn es vor dem Decrement 1 war.
In Asm schaut das so aus:
dec i     hier wird das Zero-Flag abhängig vom Ergebnis  Z oder NZ
beq ende  und hier ausgewertet

> c=c/2^((c^d)&1?p:0),d/=2);

Das ist der Kommaoperator. Er wirkt wie ein Strichpunkt, nur dass es 
wie eine Einheit aufgefasst wird, z.B. wo nur ein Ausdruck erlaubt ist.
wird z.B. auch so verwendet  uint8_t a,b,c,d;

Allerdings werden die Teilausdrücke von rechts nach links ausgewertet, 
also zuerst d/=2 (äquivalent zu d=d/2)  und dann c=c/2^((c^d)&1?p:0).

c wird halbiert (d.h. um eine Bitstelle nach rechts geschoben) und 
geXORt
mit p, wenn das Bit 0 von c^d gesetzt ist  oder
mit 0, also beibehalten, wenn das Bit 0 nicht gesetzt ist.

Wobei das ganze für mich ein Sport ist, es (natürlich auf Kosten der 
Lesbarkeit) möglichst kurz zu schreiben.

> eine anweisung  if(i>0)  kann auch als   if(i)
genauer gesagt: if(i!=0) ist das selbe wie if(i)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren