C CRC16 zurück rechnen?!

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Hallo,

Möchte gerne mal wissen, wie ich jetzt von einem Wert den ich mit dem CRC16 Wert versehen habe, wieder zurück rechnen kann.

Mein Byte -> 'A'
Als Polynom verwende ich -> 0xA001.

Als CRC16 kommt bei mir -> 0x30C0 raus.

Wie komme ich jetzt wieder auf mein 'A'?
 
Den CRC rechnet man doch auf die Rohdaten drauf oder wird die Checksumme separat geschickt?
 
Also ich mache es immer so:

Die Checksumme über die Daten bilden und diese dann mitsenden. Auf der Empfangsseite erneut die Checksumme über die Daten bilden und die errechnete Checksumme mit der empfangenen vergleichen.
 
Und damit entsteht kein Fehler? Sollte eigentlich nicht oder?
Welches CRC Verfahren nutzt du?
 
Ich nutze oft CRC16 nach CCITT mit Tabelle im Flash.

Bei dir wäre dann ja
http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html

mit Anfangswert crc= 0xFFFF


CodeBox C
uint16_t crc16_update(uint16_t crc, uint8_t a)
{
 int i;
 crc ^= a;
 for (i = 0; i < 8; ++i)
 {
    if (crc & 1)
      crc = (crc >> 1) ^ 0xA001;
    else
      crc = (crc >> 1);
   }
 return crc;
}
 
Meine sieht ein bisschen anders aus (Anfangswert = 0) ->


CodeBox C
unsigned int calcCRC16r(unsigned int crc, unsigned int c, unsigned int mask)
{
  unsigned char i;
  for(i=0;i<8;i++)
  {
    if((crc ^ c) & 1)
 {
  crc=(crc>>1)^mask;
 }
    else
    {
     crc>>=1; 
 }
    c>>=1;
  }
  return (crc);
}
 
Hallo,

Möchte gerne mal wissen, wie ich jetzt von einem Wert den ich mit dem CRC16 Wert versehen habe, wieder zurück rechnen kann.

Mein Byte -> 'A'
Als Polynom verwende ich -> 0xA001.

Als CRC16 kommt bei mir -> 0x30C0 raus.

Wie komme ich jetzt wieder auf mein 'A'?
:confused:
Da passt was nicht. CRC ist ein Hash Verfahren, da is nix mit zurück rechnen. Es ist ja keine Verschlüsselung sondern nur 1, 2 oder 4 Bytes mit einer Prüfsumme damit du erkennen kannst ob die Daten korrekt sind oder nicht. Also beim Senden von sagen wir 32 Bytes wird eine 2 Byte Prüfsumme (CRC16) angehängt. Die 32 Bytes wirst du aus den 2 Bytes nie wieder (zuverlässig) rausbekommen. Daher erstellt der Empfänger von den empfangenen Daten ebenfalls die Prüfsumme, und diese wird dann verglichen.
Sonst wäre das ja n Hammer Komprimierungsverfahren. Könnte man ja n Full-HD Film auf nen 4Kbit EEPROM speichern…

Das Knacken von Hashes ist zwar möglich, wird auch gemacht, aber definitiv nicht auf Microcontrollern. Wenn dann auf PC's mit großen Festplatten (Stichwort Rainbow Table) und viel Zeit und Glück. Und das zumeist mit rechtswidrigen Absichten.
 
Das heißt im Endeffekt. Wenn ich ein Byte habe, schicke ich noch ein Byte CRC Prüfsumme mit, richtig?
Also insgesamt zwei Bytes ( 1 Byte = Rohdaten, 2 Byte = CRC Prüfsumme )
 
Jain. Wenn du wirklich nur ein Byte schickst, ok. Kann man machen. Ich weiß zwar nicht warum man das machen sollte, aber geht. Je Byte eine Prüfsumme wäre stark kontraproduktiv da es die Bandbreite und die Rechenleistung stark einschränkt.

Aber wenn du mehr hast, Beispiel:
"Das ist ein Test"
Wäre (hex):
44 61 73 20 69 73 74 20 65 69 6E 20 54 65 73 74
Dann dazu die Prüfsumme (welcher Art auch immer, hier CRC16):
8E EF
Also würdest du senden:
44 61 73 20 69 73 74 20 65 69 6E 20 54 65 73 74 8E EF
Der Empfänger empfängt jetzt die Daten (Blau) + die vom Sender generierte Prüfsumme (grün) und generiert ebenso die Prüfsumme von dem gesamten Daten (blau). Ergibt (hier) wieder die 2 Bytes. Die werden mit den empfangenen verglichen. Wenn gleich gut, wenn nich dann nich.
Dazu sind Hashfunktionen / Prüfsummen da.

Jetzt stell dir den Datenteil mit 1MByte vor. Da ist nix mit zurück rechnen ;)

Ahja, und CRC16 ist – wie der Name schon vermuten lässt – 16 Bit breit, also 2 Bytes.
 
Einmal crc initialisieren.

Danach in einer Schlife alle Bytes behandeln:
crc = CRC_Update(uint8_t meinByte, uint16 crc); // oder eleganter crc als Pointer übergeben, Funktion hat also keinen Rückgabewert -> Routine

Danach alle Bytes übertragen plus 2 Byte CRC


Auf der Empfangsseite das selbe machen, nur mit Daten. CRC vergleichen.
 
Ich habe die Funktionen mal auf Pointer Basis umgeschrieben.



CodeBox C
unsigned int calcCRC16r(unsigned int crc, unsigned int *c, unsigned int mask)
{
  unsigned char i;
  for(i=0;i<8;i++)
  {
    if((crc ^ *c) & 1) { crc=(crc>>1)^mask; }
    else crc>>=1;
    *c>>=1;
  }
  return (crc);
}


void calcCRC16_str(unsigned int *str)
{
   unsigned int tmp;           
   
   while(*str)
   {
       tmp = *str++;
       crc = calcCRC16r(crc,&tmp, POLYNOM);
   }
}


Wenn ich ne Checksumme auf den String "hallo" berechne, bekomme ich -> 0xEC6F zurück.

Müsste doch aber 0x04D3 sein oder habe ich mich verrechnet?
 
04D3 wäre richtig
 
Du übergibst einen Pointer des Datenbytes, da gewinnst du nichts mit. Mach erst mal das mit dem Pointer wieder weg.

Dann fehlt irgendwo ggf. noch ein Startwert von crc?!

Edit:
Dein String ist bestimmt ein char Array (8bit), du arbeitest mit uinsigned int (16bit)
 
Zuletzt bearbeitet:
Da ich es erstmal auf dem PC Implementiert habe, habe ich Funktionen benutzt die ich so noch nie benutzt hatte und da lag der Fehler.
Jetzt funktioniert es.



CodeBox C
unsigned int calcCRC16r(unsigned int crc, unsigned char *c, unsigned int mask)
{
  unsigned char i;
  for(i=0;i<8;i++)
  {
    if((crc ^ *c) & 1) { crc=(crc>>1)^mask; }
    else crc>>=1;
   *c>>=1;
  }
  return (crc);
}


void calcCRC16_str(char *str)
{
   char tmp;   

   while(*str)
   {
       tmp = *str++;
       crc = calcCRC16r(crc,&tmp, POLYNOM);
   }
}



Und hier der Aufruf ->


CodeBox C
gets(InputString);
calcCRC16_str(InputString);
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)