crc Checksummen (8/16)

Code-Stücke können hier veröffentlicht werden.
Antworten
B.Nutzer
User
Beiträge: 7
Registriert: Montag 13. Januar 2014, 15:23

Hallo

irgendwie steh ich auf dem Schlauch unten habe ich zwei CRC16 Routinen eine sogar aus dem Forum und die funktionieren.
Jetzt brauch ich eine CRC8 Funktion. Habe auch eine gefunden und habe sie "dachte ich jedenfalls" von C in Python umgesetzt.
Leider klappt das ganze nicht! Statt eine Byte Wertes bekomme ich eine "monster" Zahl zurück.

Code: Alles auswählen

# Variante CRC 16 OK
BeispielDaten = ( 0xd3, 0x44, 0x3b, 0x33, 0xa3, 0x45, 0x13, 0xd5, 0x35, 0x66, 0x77, 0xff ) 
 
# ------------------------------------------------------------
# CRC16 - CRC-CCITT (XModem)
# Quelle: http://www.python-forum.de/viewtopic.php?t=958&p=4720
# ------------------------------------------------------------
def GenCCITT_CRC16(Buffer):
   # Generierung der CCITT-CRC16 Checksumme
   bitrange = range(8)  # 8 Bits   python2 xrange python3 range
   crcsum   = 0
   polynom  = 0x1021    #  CCITT Polynom

   for byte in Buffer:
      crcsum ^= byte << 8
      for bit in bitrange:
         crcsum <<= 1
         if crcsum & 0x7FFF0000: # Es gab einen Uebertrag ins Bit-16
            crcsum = (crcsum & 0x0000FFFF) ^ polynom
   return crcsum

valCrc16 = GenCCITT_CRC16 (BeispielDaten)
print ("CRC16:  ", valCrc16,  " ", hex(valCrc16))


Code: Alles auswählen

# Variante CRC 16 OK
BeispielDaten = ( 0xd3, 0x44, 0x3b, 0x33, 0xa3, 0x45, 0x13, 0xd5, 0x35, 0x66, 0x77, 0xff ) 

crcTable = ( 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
             0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
             0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
             0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
             0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
             0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
             0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
             0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
             0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
             0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
             0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
             0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
             0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
             0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
             0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
             0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
             0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
             0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
             0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
             0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
             0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
             0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
             0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
             0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
             0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
             0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
             0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
             0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
             0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
             0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
             0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
             0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0)

# ----------------------------------------------------------------------------------------------

def crc16(Buffer):
  runningCRC = 0
  for c in Buffer:
     runningCRC = crcByte(runningCRC, c)
  return runningCRC

def crcByte(oldCrc, byte):
  magic  = crcTable[(oldCrc >> 8 ^ byte) % 256] % 256
  magic2 = crcTable[(oldCrc >> 8 ^ byte) % 256] >> 8
  res = magic | ((oldCrc % 256) ^ magic2) << 8
  return res

valCrc16 = crc16 (BeispielDaten)
print ("CRC16:  ", valCrc16,  " ", hex(valCrc16))

Beide Portierungen funktionieren, einmal ohne und einmal mit vorberechneter Tabelle.
Jetzt habe ich folgendes für crc8 gefunden und umgesetzt.

Code: Alles auswählen

# Variante CRC 8 nicht funktionstuechtig
BeispielDaten = ( 0xd3, 0x44, 0x3b, 0x33, 0xa3, 0x45, 0x13, 0xd5, 0x35, 0x66, 0x77, 0xff ) 

crcTable = ( 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
             0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
             0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
             0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
             0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
             0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
             0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
             0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
             0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
             0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
             0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
             0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
             0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
             0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
             0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
             0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
             0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
             0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
             0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
             0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
             0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
             0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
             0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
             0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
             0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
             0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
             0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
             0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
             0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
             0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
             0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
             0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0)

# ----------------------------------------------------------------------------------------------

   # UPDCRC macro derived from article Copyright (C) 1986 Stephen Satchell.
   # NOTE: First argument must be in range 0 to 255.
   # Second argument is referenced twice.
   #
   # Programmers may incorporate any or all code into their programs, giving proper credit within the source. 
   # Publication of the source routines is permitted so long as proper credit is given
   # to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, Omen Technology.

   # define UPDCRC(cp,crc) ( CrcTab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
   # unsigned char ChckSum(TByte *Feld,int Lgt)
   # { unsigned short Crc = 0; int i;
   # for ( i=0 ; i<Lgt ; i++ ) Crc = UPDCRC ( *Feld++,Crc );
   # return ( (unsigned char)Crc );
   # }
   
def crc8 (Buffer):
   runningCRC = 0
   for c in Buffer:
      runningCRC = updcrc(runningCRC, c)
   return runningCRC
                         
def updcrc(crc, byte):
   crc= crcTable[(crc >> 8) & 255 ] ^ (crc << 8) ^ byte
   return crc             
                      
valCrc8   = crc8  (BeispielDaten)
print ("CRC8:          ", valCrc8,   " ", hex(valCrc8))
In C umgesetzt funktioniert die Variante mit CRC8, leider nicht in Python.
Wer meinen Fehler sieht oder eine CRC8 Implementierung hat bitte posten.
Die Pytonlib crcmod-1.7 habe ich nicht für CRC8 zum laufen gebracht....

Im Vorraus schon einmal Danke

B.Nutzer
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Ich habe mir deinen Code jetzt nicht genau angeschaut, aber dein Problem und die Zeile 61 deuten sehr stark darauf hin, dass du die Werte nicht korrekt abschneidest. Wenn du in C einen Shift "nach links" machst, dann fallen "die linken" Bytes raus. Integer in Ptyhon können beliebig groß werden, daher gehen die Bits nicht verloren. Daher auch die ganzen "% 256" oben im Code. Die solltest du bei dir auch an den entsprechenden Stellen einbauen.
Das Leben ist wie ein Tennisball.
B.Nutzer
User
Beiträge: 7
Registriert: Montag 13. Januar 2014, 15:23

Hallo und Danke für die schnelle Antwort

Das die Bits bei dem Shift nicht automatisch rausfallen war mir nicht bewusst, in Nachhinein aber verständlich.
Hier muss ich wohl noch an meinen Python-Wissen arbeiten.
Ich habe jetzt mit %256 quasi den Bytetyp erzwungen, das Ergebniss sieht auch schon fast gut aus.
Leider ist das Ergebniss immer 255 (0xFF) bei unterschiedlichen BeispielDaten.

Falls jemand den Fehler sieht ....

Code: Alles auswählen

def updcrc(crc, byte):
   crc= crcTable[((crc >> 8) & 255) % 256 ] ^ ((crc << 8) % 256) ^ byte
   return crc             

Danke
B.Nutzer
BlackJack

@B.Nutzer: Das hier ``((crc << 8) % 256)`` schiebt alle Bits um 8 Bits nach rechts und löscht sie dann alle, also dieser Teilausdruck ist *immer* 0. Ich denke mal das ist nicht gewollt. Ich wette im Originalcode ist `crc` *nicht* vom Typ `uint8_t` (oder `char`).
B.Nutzer
User
Beiträge: 7
Registriert: Montag 13. Januar 2014, 15:23

Irgendwie "hoffentlich gelöst".
Mir fiel auf das wenn ich kein Cast auf 8Bit durchführe (%256) kommt bei der langen Integerzahl die richtigen letzten 8Bit heraus.
Bei einer kleinen Testreihe mit der C-Funktion und meinen Python-Script stimmten die Prüfsummen :-)
Also wurde das Endergebniss am Schluß einfach auf 8Bit maskiert und es funktioniert.

Danke an alle Beteiligten für die Denkanstösse.

Code: Alles auswählen

BeispielDaten = ( 0xd3, 0x44, 0x3b, 0x33, 0xa3, 0x45, 0x13, 0xd5, 0x35, 0x66, 0x77, 0xff )
#
# crcTable von obigen Beispiel
#
def crc8 (Buffer):
   runningCRC = 0
   for c in Buffer:
      runningCRC = updcrc(runningCRC, c)
   rtstCRC = runningCRC & 0xff
   return rtstCRC
                         
def updcrc(crc, byte):
   crc= crcTable[((crc >> 8) & 255) ] ^ ((crc << 8) ) ^ byte 
   return crc             

valCrc8 = crc8 (BeispielDaten)
print ("CRC8:  ", valCrc8,  " ", hex(valCrc8))
Gruß B.Nutzer
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@B.Nutzer: Du implementierst einen Algorithmus, ohne überhaupt das grundlegendste Wissen über Bit-Operationen zu haben?????
Bei jedem neuen Zeichen werden die oberen 8 Bit von crc als Index in die crcTabelle benutzt und mit byte verknüpft, werden die unteren 8 Bit einfach nach oben geschoben werden. Richtig lautet die Funktion also:

Code: Alles auswählen

def updcrc(crc, byte):
    return crcTable[crc >> 8] ^ ((crc & 255) << 8) ^ (byte & 255)
Einrücktiefe sind vier Leerzeichen!
B.Nutzer
User
Beiträge: 7
Registriert: Montag 13. Januar 2014, 15:23

@Sirius3: Danke für den Korrekturhinweis

Da ich den Alogrithmus in C schon verstanden hatte scheiterte ich jedoch bei der Portierung auf Python.
Dein CodeSnippet ist natürlich das schönere/richtigere und wir ab sofort von mir entsprechend benutzt.

Danke B.Nutzer
Der_Michl82
User
Beiträge: 4
Registriert: Sonntag 2. Februar 2014, 20:42

Servus,

ich kämpfe mit der gleichen Thematik und habe deine Code für CRC8 ausprobiert, allerdings gibt er mir immer als CRC8 den ersten Wert aus den Beispieldaten aus.

Gruß

Michael
B.Nutzer
User
Beiträge: 7
Registriert: Montag 13. Januar 2014, 15:23

@Der_Michel82

Hi, kann dein Problem leider nicht nachvollziehen.
Wenn ich mir die Sourcen aus dem Artikel entsprechend zusammen kopiere kommt
CRC8: 42 0x2a heraus.

Gruß B.Nutzer
Antworten