Hilfe gesucht. CRC8-Prüfsumme berechnen

Hallo,

ich probiere nun sein 2 Wochen einen Code zum berechnen einer CRC8-Prüfsumme zu schreiben. Die Beispiele bei wikipedia sind dabei nicht sehr hilfreich. Folgende Seite erscheint mir sehr gut, aber trotzdem kommt bei mir nie das richtige Ergebnis heraus: Sunshine's Homepage - Understanding CRC

Ich habe mir ein einfaches Beispiel erstellt:

Bitfolge: 10110001 01011101 00000000 (24 Bit)

CRC8-Polynom: 100101111

Bei der Polynomdivision müsste am Ende 00001101 herauskommen. Mein Arduino spuckt mir aber jedes Mal einen neuen Wert aus. Findet irgendjemand meinen Denkfehler im Code? Ich wäre echt dankbar, wenn jemand den Knoten in meinem Kopf lösen könnte, da ich hier sonst noch verrückt werde.

PS: Mein Code ist angelehnt an das Kapitel 4.1 “Simple CRC-8 shift register implementation for one byte input data” aus dem aufgeführten Link.

Vielen Dank im Vorraus.

CRC8_Test_einfach2.ino (1.34 KB)

Brombeerle: Bitfolge: 10110001 01011101 00000000 (24 Bit)

Also Du möchtest eine 8-Bit CRC aus diesen drei Datenbytes brerechnen. was soll das Ergebnis sein? Und hast Du die zwei oder drei wichtigsten 8-Bit CRC Berechnungsvorschriften mal daraufhin getestet, ob "Deine" CRC-Berechnung vielleicht darunter ist? Für gängige CRC Prüfsummen braucht man nämlich überhaupt keinen neuen Code zu schreiben, weil es den Code für die gängigen CRCs schon seit circa 40-50 Jahren gibt. Und "gängig" sind "die gängigen CRC-Berechnungen" deshalb, weil sie immer wieder verwendet werden, und sich nicht jeder für irgendwelchen Pillepalle eine neue Variation einfallen läßt.

Das Ergebnis soll wie bereits erwähnt 00001101 sein. Eigentlich möchte ich das Ergebnis aus den ersten 2 Datenbytes berechnen, aber bei einem CRC 8 Polynom müssen für die Polynomdivision noch 8 Nullen an die Nutzdaten angehängt werden.

Und ja, ich habe nach bereits bestehenden Codes gesucht, aber nichts zu meinem speziellen Polynom gefunden. Das Polynom ist auch definitv 100101111. Ich kann dies nicht ändern.

Wenn der Code für 2 Bytes funktioniert möchte ich ihn für mein Problem mit mehr Bytes anpassen. Aber da ich mir das Beispiel für die Code Kontrolle per Hand berechne, möchte ich erstmal bei 2 Bytes bleiben.

jurs: ... Für gängige CRC Prüfsummen braucht man nämlich überhaupt keinen neuen Code zu schreiben, weil es den Code für die gängigen CRCs schon seit circa 40-50 Jahren gibt. Und "gängig" sind "die gängigen CRC-Berechnungen" deshalb, weil sie immer wieder verwendet werden, und sich nicht jeder für irgendwelchen Pillepalle eine neue Variation einfallen läßt.

Du plädierst demnach dafür, per copy&paste zu programmieren (oder sonstwie etwas Fertiges zu nehmen), anstatt selbst etwas zu programmieren? Auch, wenn es dabei um den Spaß an der Sache oder ums Lernen geht?

Na, ich weiß nicht ...

Gruß

Gregor

Also mir würde ein Tipp helfen, was ich evtl. falsch mache. Ich habe eigene Codes ausprobiert und nachdem diese nicht wirklich funktioniert haben, habe ich nach Hilfe und Anregungen im Internet gesucht. Dabei bin ich auf den in meinem ersten post erwähnten Link gekommen, der das Thema sehr ausführlich und gut erklärt. Ich habe weiterhin Spaß am Programmieren, bin aber bei weitem nicht der Beste darin. Daher benötige ich manchmal eben Hilfe und schäme mich auch nicht dafür. Ich bin über jeden Tipp und jede Anregung froh und dankbar :)

Ich habe, da der Sandmann laut ruft, schnell mal was zusammengeschustert (K&E), wo “Pruefsumme: 1101” rauskommt (Sketch enthält Fehler!):

int tasterstatus = HIGH;

#define CRC8_Polynom 0B00101111 //MSB weglassen, da 1 XOR 1 sowieso immer 0 wird
byte input[] = {0xB1, 0x5D, 0x00};
byte crc8 = 0x00; //8-Bit Schieberegister

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (tasterstatus == HIGH)
  {
    byte crc8 = Compute_CRC8_Simple(input);
    Serial.println("Pruefsumme: ");
    Serial.println(crc8, BIN);
    tasterstatus = LOW;
  }
}

byte Compute_CRC8_Simple(byte* bytes)
{
  const byte generator = CRC8_Polynom;
  byte crc = 0; /* start with 0 so first byte can be 'xored' in */

  for (byte j = 0; j < sizeof(bytes); j++)
  {
    crc ^= bytes[j]; /* XOR-in the next input byte */

    for (int i = 0; i < 8; i++)
    {
      if ((crc & 0x80) != 0)
      {
        crc = (byte)((crc << 1) ^ generator);
      }
      else
      {
        crc <<= 1;
      }
    }
  }
  return crc;
}

Quelle wie in #0 angegeben.

Das ist ja super, vielen Dank für deine wirklich sehr schnelle Hilfe. Die Variante mit den einzelnen Bytes ist für mein nachfolgendes Problem zwar etwas langwieriger da ich einen zusammenhängenden Bitstrom habe, aber die Aufteilung in einzelne Bytes bekomme ich auf jeden Fall hin. Nun kann ich gut schlafen und morgen weiter werkeln :D

Brombeerle:
Das ist ja super, vielen Dank für deine wirklich sehr schnelle Hilfe. Die Variante mit den einzelnen Bytes ist für mein nachfolgendes Problem zwar etwas langwieriger da ich einen zusammenhängenden Bitstrom habe, aber die Aufteilung in einzelne Bytes bekomme ich auf jeden Fall hin. Nun kann ich gut schlafen und morgen weiter werkeln :smiley:

Na bravo, wenn’s das ist und so sein soll, dann mein Glückwunsch an agmue und Dich, dass ihr den Knoten gelöst habt!

Ich hatte am späten Abend auch noch was an Code in meine Arduino-IDE kopiert, hier kompiliert und laufen lassen, aber für die von Dir genannten Input-Bytes und das Generator-Polynom bekomme ich ein anderes Ergebnis für die CRC-Prüfsumme, und zwar ist mein Ergebnis für die CRC über alle drei Bytes:
C4 hexadezinal bzw,
196 dezimal btw.
11000100 in Binärdarstellung

Edit/Nachtrag: Wenn man nur die CRC über die ersten zwei Bytes bildet, dann stimmt es und genau das macht argmue ja auch in der for-Schleife

for (byte j = 0; j < sizeof(bytes); j++)

bytes ist ein Pointer auf ein byte-Array, und sizeof() eines Pointers ist auf der Atmega-Plattform 2 Bytes, über die er die CRC-Prüfsummenbildung iteriert.

Also alles OK, CRC-Berechnung über die ersten zwei Bytes liefert 1101 als binäres Ergebnis.
Und das CRC Ergebnis über alle 3 Bytes interessiert Dich eigentlich gar nicht. Na dann gute Nacht, jetzt gehe ich auch zu Bett.

jurs: ... sizeof() eines Pointers ist auf der Atmega-Plattform 2 Bytes ...

Da sage ich dann auch "na bravo". Danke für den Hinweis!

Richtig erkannt, sizeof(pointer) liefert hier zufällig den gewünschten Wert. Die Anzahl der Bytes muß zusätzlich an die Funktion übergeben werden, sonst wird das nichts.

Ich kann programmieren, was ich will, es kommt immer “Pruefsumme: 1101” raus :wink:

bool einmal = true;

#define CRC8_Polynom 0B00101111 //MSB weglassen, da 1 XOR 1 sowieso immer 0 wird
byte input[] = {0xB1, 0x5D};

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (einmal) {
    byte crc8 = Compute_CRC8_Simple(input, sizeof(input));
    Serial.print("Pruefsumme: ");
    Serial.println(crc8, BIN);
    einmal = false;
  }
}

byte Compute_CRC8_Simple(byte* zeiger, const byte laenge) {
  const byte polynom = CRC8_Polynom;
  byte crc = 0; /* start with 0 so first byte can be 'xored' in */
  for (byte j = 0; j < laenge; j++) {
    crc ^= zeiger[j]; /* XOR-in the next input byte */
    for (byte i = 0; i < 8; i++) {
      if ((crc & 0x80) != 0) {
        crc = (byte)((crc << 1) ^ polynom);
      } else {
        crc <<= 1;
      }
    }
  }
  return crc;
}

Zur Erklärung für den TO: Anstatt ein Feld an die Funktion zu übergeben, wird nur der Zeiger auf das Feld übergeben. Die Länge des Feldes geht dabei “verloren”, weshalb sie als eigene Konstante übergeben werden muß. Details bitte in der Fachliteratur nachlesen :slight_smile:

agmue: Ich kann programmieren, was ich will, es kommt immer "Pruefsumme: 1101" raus ;)

Das ist ein gutes Zeichen. Vielleicht hast Du die Weltformel gefunden! Boh!

Gruß

Gregor

PS: SCNR

Wohl nicht, denn "1101" entspricht 13, die Antwort lautet aber bekanntermaßen "42".

Vielleicht muß man noch die passende Zahlenbasis finden, damit die Antwort paßt?

BTW, wie weit ist eigentlich der Versuch gediehen, die Frage zur Antwort zu finden? <gd&r>

agmue: Wohl nicht, denn "1101" entspricht 13, die Antwort lautet aber bekanntermaßen "42".

42/2=21 21-8=13.

Also wenn man es mehr allgemein als speziell sieht, ist die 13 so gut wie die 42. Alles ganz simple Mathe (und sogar ohne Pi).

:-)

Gregor

PS: Außerdem ist heute Freitag. Da ist 13 sowieso fast das Gleiche wie 42.

Ich kann es so programmieren, dass unterschiedliche Eingaben unterschiedliche Ergebnisse liefern.

const byte CRC8_Polynom=0x2F; 

byte input[] = {0xB1, 0x5D};

void setup() {
   Serial.begin(9600);
   byte crc8 = Compute_CRC8_Simple(input, sizeof(input));
   Serial.print("Pruefsumme: ");
   Serial.println(crc8, BIN); //  00001101

   input[0]++;
   input[1]++;
   crc8 = Compute_CRC8_Simple(input, sizeof(input));
   Serial.print("Pruefsumme: ");
   Serial.println(crc8, BIN);  // 01101000
}

Sheldon soll sich der Frage genähert haben, wurde aber durch die Dummheit seines obersten Chefs in eine Sinnkrise gestürzt. Ruhen also die Hoffnungen auf dem Doktor (Dr Who).

Damit wünsche ich einen schönen Anfang des Endes, also des Wochenendes :)