Forum: Mikrocontroller und Digitale Elektronik CRC-16 Prüfsumme (serielle Übertragung)


von Olaf R. (gruser)


Lesenswert?

Hallo zusammen,

ich habe hier den untenstehenden Code gefunden zur Berechnung einer 
Checksumme (CRC-16), allerdings bekomme ich in den beiden Bytes des 
Ergebnisses jeweils nur eine "1".

Was mache ich falsch? Wenn ich aus 3 Bytes einen CRC-Wert ermitteln
möchte, muss ich die Funktion doch einfach nur 3x aufrufen:

  DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,Wert1,0xA001);
  DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,Wert2,0xA001);
  DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,Wert3,0xA001);

Die beiden Bytes frage ich mit DEVICE_CRC16.low8 bzw. DEVICE_CRC16.high8
ab. Bei den Deklarationen von Wert1-3 habe ich bereits alles probiert
(uns16/ uns8, char) - am Ergebnis hat es nichts geändert.
Außerdem glaube ich nicht dass das Polynom A001 (bzw. 
"1010000000000001") dem Polynom von CRC16 entspricht...

Kennt sich hier jemand gut aus?

Grüße
Olaf









//- calcCRC16r ------------------------------------------------------
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);
}
//-------------------------------------------------------------------

Aufruf der Funktion im Programm:

{
//...
  unsigned int DEVICE_CRC16=0;
  DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,chr,0xA001);
//...
}

von so nicht (Gast)


Lesenswert?

Ja. Mein code :

PROCEDURE calcCRCbyte(data:BYTE;VAR crc:WORD);
VAR i:BYTE;
BEGIN
 FOR i:=0 TO 7 DO BEGIN
   IF ((data and $01)XOR(crc AND $0001)<>0) THEN BEGIN
     crc:=crc shr 1;
     crc:= crc XOR $A001;
    END
   ELSE BEGIN
     crc:=crc shr 1;
    END;
   data:=data shr 1;
  END;
END;

Deiner scheint etwas kuerzer zu sein, dh etwas wegzulassen.

von Michael K. (mmike)


Lesenswert?

Hier einer in C:

HEADER:
1
/*****************************************************************************
2
* Name: crcCCITT()
3
* Eingaben: - Laenge der Nachricht
4
* - Zeiger auf die Nachricht
5
* - CRC-Vorladewert, Startwert ist 0xFFFF
6
* Ausgaben: - CRC von der Nachricht
7
* Beschreibung: Die Funktion berechnet den CRC von der Nachricht nach dem
8
* Generatorpolynom g(x) = x^16+ x^12 + x^5 + 1 (CCITT-Polynom).
9
*****************************************************************************/
10
 
11
#ifndef __CRC16_H__
12
#define __CRC16_H__
13
 
14
#include <inttypes.h>
15
 
16
#define poly  0x1021    // g(x) = (x^16+) x^12 + x^5 + 1
17
 
18
uint16_t crcCCITT(uint8_t size, volatile uint8_t * mem, uint16_t crc);
19
 
20
#endif

IMPLEMENTATION:
1
uint16_t crcCCITT(uint8_t size, volatile uint8_t * mem, uint16_t crc)
2
{
3
  //  static int i,j;
4
  uint8_t i;
5
  uint8_t j;
6
 
7
  //  static unsigned short b;
8
  uint8_t b;
9
 
10
  //  static unsigned char m;
11
  uint8_t m;
12
 
13
  // While (more message bits)
14
  for (i = 0; i < size; i++)
15
  {
16
    m = mem[i];
17
    for( j = 8; j; j-- )
18
    {
19
      b = 0;
20
      if(crc & 0x8000)
21
        b++;
22
      // Shift the register left by one bit,
23
      crc <<= 1;
24
      if ((m & 0x80) != 0) crc |= 1;
25
      m <<= 1;
26
      // If (a 1 bit popped out of the register during step 3)
27
      // Register = Register XOR Poly.
28
      if (b != 0) 
29
        crc ^= poly;
30
    }
31
  }
32
  return crc;
33
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.