CAN CRC Berechnung

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Berechnung einer CAN CRC Checksumme

Ein CAN-Frame

CAN Frame von SOF bis vor den Beginn des CRC Feldes (Dividend) 00000100100000000100000000001110111
Generatorpolynom (Divisor) x15+x14+x10+x8+x7+x4+x3+1
= 1100010110011001

Im Prinzip geht es darum, den um 15 Stellen erweiterten Dividenden mit Rest durch den Divisor zu teilen. Der Rest entspricht der CAN CRC Checksumme.

Der einfachste Weg diese Division in einem µController durchzuführen besteht darin, den Dividenden so weit nach links zu schieben, bis eine 1 auf der linken Seite steht. Nun wird der vordere Teil des Dividenden mit dem Divisor einer XOR-Funktion verknüpft, was einer Subtraktion modulo 2 entspricht. Das jeweilige Ergebnis wird dann wieder so weit nach links geschoben, bis abermals eine 1 vorne steht und die nächste XOR-Verknüpfung stattfinden kann.

Anstatt die Multiplikation komplett auszuführen und erst danach modulo dem Generatorpolynom zu reduzieren, kann auch bereits während der Multiplikation reduziert werden.

Hier habe ich ein kleines Beispiel für die Berechnung dargestellt. Es handelt sich um ein empfangenes CAN-Frame, bei dem die Stuffingbits schon entfernt wurden, mit einem 11-Bit Identifier und 2 Bytes Datenlänge. Dies kann sich im ungünstigsten Fall durch einen 29-Bit Identifier und 32 Datenbits auf insgesamt 69 Stellen ausweiten.

 
100100000000100000000001110111000000000000000
1100010110011001||||||||||||||||||||||||||||| XOR
----------------|||||||||||||||||||||||||||||
 1010101100100010||||||||||||||||||||||||||||
 1100010110011001|||||||||||||||||||||||||||| XOR
 ----------------||||||||||||||||||||||||||||
  1101110101110110|||||||||||||||||||||||||||
  1100010110011001||||||||||||||||||||||||||| XOR
  ----------------|||||||||||||||||||||||||||
   001100011101111000||||||||||||||||||||||||
     1100010110011001|||||||||||||||||||||||| XOR
     ----------------||||||||||||||||||||||||
      000001011100001001110||||||||||||||||||
           1100010110011001|||||||||||||||||| XOR
           ----------------||||||||||||||||||
            1111101110101111|||||||||||||||||
            1100010110011001||||||||||||||||| XOR
            ----------------|||||||||||||||||
             01111100011011011|||||||||||||||
              1100010110011001||||||||||||||| XOR
              ----------------|||||||||||||||
               01111010100001000|||||||||||||
                1100010110011001||||||||||||| XOR
                ----------------|||||||||||||
                 01100001001000100|||||||||||
                  1100010110011001||||||||||| XOR
                  ----------------|||||||||||
                   00001111101110100000||||||
                       1100010110011001|||||| XOR
                       ----------------||||||
                        01111100011100100||||
                         1100010110011001|||| XOR
                         ----------------||||
                          01111010111110100||
                           1100010110011001|| XOR
                           ----------------||
                            01100000110110100
                             1100010110011001 XOR
                             ----------------
                              000010000101101 das ist die CRC Checksumme

Wenn der Rest kürzer als der Divisor geworden ist, kann nicht weiter geteilt werden. Die 15 niederwertigsten Bits bilden dann die CRC-Checksumme, die der Sender den Datenbytes anhängt. Der Empfänger vergleicht seine selbst errechnete Checksumme mit der Checksumme im CAN-Frame um zu überprüfen, ob die Nachricht Fehler enthält. Ich habe das Linksschieben hier nicht mit aufgeführt, sondern den Divisor einfach unter die nächste 1 gesetzt.