Forum: Compiler & IDEs CRC8 berechnen


von Andi79 (Gast)


Lesenswert?

Hallo

suche einen einfachen CRC8-Code für den MSP 430. Ich habe einen 32 Bit 
Wert. Die ersten 24 Bit sollen überprüft und mir dem Wert der letzten 8 
Bit verglichen werden. Die Checksumme soll nach SAE J1850 mit dem 
Generatorpolynom 1D und dem Initalwert 0xFF und XOR out=0xFF berechnet 
werden. Wäre echt super wenn jemand dafür ein Code-Beispiel hat.
mfg Andi

: Gesperrt durch User
von Arne (Gast)


Lesenswert?

1
uint8_t CalculateCRC8Internal(uint8_t inCRC, uint8_T inByte)
2
{
3
  inByte ^= inCRC;
4
  inCRC = 0;
5
  if(inByte & 0x01) inCRC  = 0x5E;
6
  if(inByte & 0x02) inCRC ^= 0xBC;
7
  if(inByte & 0x04) inCRC ^= 0x61;
8
  if(inByte & 0x08) inCRC ^= 0xC2;
9
  if(inByte & 0x10) inCRC ^= 0x9D;
10
  if(inByte & 0x20) inCRC ^= 0x23;
11
  if(inByte & 0x40) inCRC ^= 0x46;
12
  if(inByte & 0x80) inCRC ^= 0x8C;
13
  return inCRC;
14
}

von Arne (Gast)


Lesenswert?

vergiss meine Post. Hab nicht auf das Generatorpolynom  geachtet.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn ich den Dallas-1wire-Code aus der avr-libc:
1
    uint8_t
2
    _crc_ibutton_update(uint8_t crc, uint8_t data)
3
    {
4
        uint8_t i;
5
6
        crc = crc ^ data;
7
        for (i = 0; i < 8; i++)
8
        {
9
            if (crc & 0x01)
10
                crc = (crc >> 1) ^ 0x8C;
11
            else
12
                crc >>= 1;
13
        }
14
15
        return crc;
16
    }

mit dem SAE-J1850-Polynom vergleiche, dann solltest du diesen benutzen
können, indem du die 0x8C durch eine 0xB8 ersetzt.  Was allerdings
"XOR out=0xFF" meint, verstehe ich nicht.

von Rolle (Gast)


Lesenswert?

Vorsicht, das Beispiel von Jörg zeigt die INVERSE -Berechnug der CRC.
Bei seriellen Übertragungen werden üblicherweise Datenbytes mit LSB 
zuerst übertragen, nur die CRC mit MSB zuerst. Um den gleichen 
Sendealgorythmus zu verwenden wird dann die CRC invers berechnet und MSB 
steht im BIT0 und alles passt wieder.

also:
Man beginnt mit crc = 0xff, führt dann mit jedem Byte die Berechnung von 
Jörg fort und und hängt am Schluss die crc invertiert (out = crc^0xff) 
an den Datenstrom an. Das hat den Vorteil dass bei einer neuerlichen 
Berechnung der CRC im Empfänger über alle Bytes (also Daten + 
invertierte CRC) ein  (für das Polynom typischer) konstanter Wert heraus 
kommt.


Viel Spass noch

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolle schrieb:
> Vorsicht, das Beispiel von Jörg zeigt die INVERSE -Berechnug der CRC.

Ja, wobei ich (mangels einer auf die Schnelle zu findenden Spec) davon
ausgegangen bin, dass SAE J1850 wie fast alle anderen seriellen
Übertragungen ebenfalls mit dem LSB beginnt, sodass man den Dallas-
Algorithmus 1:1 benutzen kann.

Das ist eigentliche Problem mit den CRCs, man muss nicht nur den
Startwert und das Generatorpolynom kennen, sondern auch noch die
Bitreihenfolge.  Sinnvollerweise sollte man also bei jedem praktisch
beschriebenen Algorithmus auch gleich noch eine Beispielsequenz
dabei stehen haben.

von Michael (Gast)


Lesenswert?

Hallo!

Ich habe ein kleines Verständnisproblem mit der Matematik hinter dieser 
Berechnung, darum habe ich versucht einen Code für eine Bit-weise 
berechnung geschrieben. Soweit sogut, nur habe ich das Problem, wenn ich 
als Startwert 0xFF am Beginn des Dataframes anhänge bekomme ich einen 
falschen CRC-Wert. Der Code wurde mit  einer Routine aus dem Netz 
verifiziert. (http://www.zorc.breitbandkatze.de/crc.html)
Dort gibt es auch die Möglichkeit den Startwert "direct" oder 
"nondirect" anzugeben. "direct" liefert das richtige Ergebnis, 
"nondirect" das gleiche Ergebniss wie mein Code.
Kan mir jemand den Unterschied erklären?

von Klaus (Gast)


Lesenswert?

1.Methode (die da "direct" genannt wird)
Der Startwert ist der Wert den man zu Begin einer Berechnung in die CRC 
Variable schreibt. Üblicherweise ist das meist 0x00 oder 0xff...

2.Methode (nondirect)
Initialisiert man die CRC-Variable mit 0x00 und schreibt dafür 0xff an 
den Anfang des Datenframes, dann startet man quasi mit der CRC von 0xff 
nach der 1.Methode.

Es gilt halt was Jörg schon ausgeführt hat

Jörg Wunsch schrieb:
> Das ist eigentliche Problem mit den CRCs, man muss nicht nur den
> Startwert und das Generatorpolynom kennen, sondern auch noch die
> Bitreihenfolge.  Sinnvollerweise sollte man also bei jedem praktisch
> beschriebenen Algorithmus auch gleich noch eine Beispielsequenz
> dabei stehen haben.

Die Regel ist einfach die: Man benutze den gleichen Algorithmus wie die 
Gegenstelle !!!

von paule (Gast)


Lesenswert?

Hallo,

sehe ich genauso mit der Gegenstelle.
Hatte auch das Problem, habe aber dann einfach die ganze Bitdreherei 
gelassen. So lange dies nicht verlangt ist nach einem Standard macht man 
es einfach so, wichtig ist nur dabei das Sende und Empfangsstation es 
gleich machen.


Gruß
paule

von Jörg Stamm (Gast)


Lesenswert?

Hallo,

ich habe ein ähnliches Problem.

Es geht um eine CRC8 mit folgenden Parametern
x8+x5+x3+x2+x1+x0 (i.e. 0x2F with the leading one omitted)
The initial start value is 0xFF while the target value is 0x00.

Ich benutze folgenden Code:
1
// Polynom 0x2F
2
// start wert 0xFF
3
// Target 0x00 
4
__int8 crc8__update( __int8 crc, __int8 data)
5
{
6
  __int8 i;
7
8
  crc = crc ^ data;
9
    for (i = 0; i < 8; i++)
10
    {
11
        if (crc & 0x80)
12
            crc = (crc << 1) ^ 0x2F;//0x1D;//0x8C;
13
        else
14
            crc <<= 1;
15
    }
16
17
  return crc;
18
}
19
20
...
21
22
  unsigned __int8 buffer[]={ 0x40,0x2B,0x03 }; //B6 CRC
23
  unsigned __int8 crc;
24
25
  crc=0xFF;
26
  for( unsigned __int8 i = 0 ; i < sizeof(buffer) ; i++ )
27
  {
28
    crc=crc8__update( crc, buffer[i] );
29
  }
30
  printf( ":%02X", crc );
31
  printf( ":%02X", crc^0x00 );
32
  printf( ":%02X", crc^0xFF );

Richtig gerechnete Beispiele von Strings mit CRC8:
0x402901 15
0x402B83 55

Vielleicht sieht ja jemand meine Fehler ?
Was bedeutet Target 0x00 ?

Gruß
Jörg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Stamm schrieb:

> ich habe ein ähnliches Problem.

Auch wenn das Problem ähnlich scheint: oft ist es am Ende doch was
anderes => eigenen Thread aufmachen.

>   __int8 i;

Lass dich nicht mit __int8 erwischen.  Bezeichner mit zwei führenden
Unterstrichen sind `reserved for the implementation'.  Und die
`implementation' stellt dir gemäß dem aktuellen C-Standard über
den Header <stdint.h> den Datentyp int8_t bereit (wobei ich mich
gerade frage, ob du nicht eher uint8_t nehmen willst).

> Vielleicht sieht ja jemand meine Fehler ?

Wenn du uns verrätst, was für dich denn der Fehler ist?

> Was bedeutet Target 0x00 ?

Dass nach dem vollständigen Algorithmus über Datenstrom + CRC eine
0 rauskommen soll.  Das ist aber normal.

von Jörg Stamm (Gast)


Lesenswert?

Hey,

der Fehler ist, daß die CRC nicht richtig ausgerechneet wird.

Auch wenn ich die CRC mit in die Berechnung einfließen lasse, komme ich 
nicht auf 0x00.

Ich habe zu Testzwecken die Routine in VC++ getestet, da muß man doch 
__int8 für eine 8bit Integer benutzen ? Nicht das da mein Fehler liegt.

Gruß
Jörg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Stamm schrieb:
> der Fehler ist, daß die CRC nicht richtig ausgerechneet wird.

Dann mach' bitte dein Beispiel verständlicher, oder schreib' uns,
wofür die CRC da gut ist.  Irgendjemand wird ja die "Gegenstelle"
sein, der das so festgelegt hat.  Vielleicht ist dessen Beschreibung
ja verständlicher als dein Text.

> Ich habe zu Testzwecken die Routine in VC++ getestet, da muß man doch
> __int8 für eine 8bit Integer benutzen ?

Keine Ahnung, kenne ich nicht.

von Klaus W. (mfgkw)


Lesenswert?

Jörg Stamm schrieb:
> Ich habe zu Testzwecken die Routine in VC++ getestet, da muß man doch
> __int8 für eine 8bit Integer benutzen ?

Man kann auch für VC++ die stdint.h nachrüsten, dann kann man wie 
überall sonst auch uint8_t nehmen.

http://msinttypes.googlecode.com/svn/trunk/stdint.h
http://msinttypes.googlecode.com/svn/trunk/inttypes.h

von Joe (Gast)


Lesenswert?

Hi,

habe gesehen ihr habt euch über das Thema CRC anch SAE J1850 berechnen 
schon ordentlich ausgetauscht. Ich brauche auch einen C-Code, um eine 
CRC-Prüfsumme gemäß SAE J1850 folgender Botschaft zu berechnen:

C7 40 0C 00 00 00 00

Laut Vorgabe des Autors dieser CAN-Botschaft soll für die CRC-Prüfsumme 
der Wert 53(hex) rauskommen. Da ich noch recht wenig Erfahrung in C und 
auch sonst KEINERLEI Erfahrung mit Embedded Systems o.ä. habe, wäre ich 
über einen einfachen C-Code für mein Problem sehr dankbar. Ihr habt oben 
bereits zum Beitrag von Jörg geschrieben, was man abändern muss, aber so 
ganz klar war mir das leider nicht. Kann mir bitte jemand einen 
vollständigen C-Code posten?

Vielen Dank für jede Antwort,

Joe

von Oliver (Gast)


Lesenswert?

Joe schrieb:
> Kann mir bitte jemand einen
> vollständigen C-Code posten?

Aber gerne:
1
 crc = 0x53;

Aller weitere steht in den Beiträgen weiter oben. Wenn dier da snicht 
ausreicht, wirst du den Umweg über "Ich lerne richtig C, von Anfang an" 
nehmen müssen.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

und bitte hör auf uralte Threads zu kapern, nur weil eines der Buzzwords 
im Titel mit dem übereinstimmt, was du brauchst.

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.