Seite 1 von 1

crc Checksummen (8/16)

Verfasst: Montag 13. Januar 2014, 15:45
von B.Nutzer
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

Re: crc Checksummen (8/16)

Verfasst: Montag 13. Januar 2014, 15:56
von EyDu
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.

Re: crc Checksummen (8/16)

Verfasst: Dienstag 14. Januar 2014, 08:10
von B.Nutzer
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

Re: crc Checksummen (8/16)

Verfasst: Dienstag 14. Januar 2014, 09:07
von 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`).

Re: crc Checksummen (8/16)

Verfasst: Dienstag 14. Januar 2014, 14:06
von B.Nutzer
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

Re: crc Checksummen (8/16)

Verfasst: Dienstag 14. Januar 2014, 14:33
von Sirius3
@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!

Re: crc Checksummen (8/16)

Verfasst: Dienstag 14. Januar 2014, 15:36
von B.Nutzer
@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

Re: crc Checksummen (8/16)

Verfasst: Sonntag 2. Februar 2014, 20:46
von Der_Michl82
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

Re: crc Checksummen (8/16)

Verfasst: Montag 24. Februar 2014, 10:36
von B.Nutzer
@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