EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Need an explanation for calculating the CRC for a CAN network

Started by Unknown April 15, 2008
On Apr 17, 2:47 am, Neil <NeilKu...@worldnet.att.net> wrote:
> The Polynomial must be different > > Should it be 0xC599 ?
Well, the number 0x4599 seems to be popping up in a lot of the CAN examples, and 0xC599 is 16 bits, not 15 so I don't know how that would change anything since the results are always truncated to 15 bits. : ( Anyone?? Is there a bug in the example code that Lasse provided? -Will
/Bump

Anyone know why the example code provided by Lasse does not match the
CRC generated by the hardware I'm using?  If it matters (shouldn't)
I'm using an Atmel AT90CAN128 chip.  But any CAN controller should
generate the same bit patterns unless I am wildly mistaken, which does
happen sometimes...

-Will
On Apr 15, 8:08=A0pm, larkmore@aol.com wrote:
> Can anyone out there explain how to calculate the 15 bitCRCfield for > a Controller Area Network message (specifically the extended frame > format)? =A0I don't understand the code given in the Bosch specification > (not even sure which language it's written in) and the only other > example I found was very obfuscated C code. =A0Any takers? > -Will
Hi, You can try my CRC code generator: http://mcgougan.se/universal_crc As someone pointed out the polynomial for the CAN CRC is apparently: x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1 This polynomial can be represented as 0x4599 (x^0 maps to LSB, x^15 is implied 1). Knowing this my utility can then be invoked like this: universal_crc --bits=3D15 --poly=3D0x4599 This will produce ANSI C code for calculating the CRC and print it to stdout. The utility has various other options that you might need depending on how the CAN CRC is defined (initial value of the CRC register, final XOR, reversed mode, etc.). There are also different CRC algorithms to choose from that have various performance characteristics. Let me know if you found this useful! Best regards, Danjel McGougan
On Apr 16, 12:49=A0am, Lasse Langwadt Christensen <llcn...@fonz.dk>
wrote:
[...]
> the pseudo in c would be something like this: > (untestet, inefficient, written in 30 seconds ...) > > unsigned shortCRC(unsigned short input) // input only one bit !!! > { > =A0 =A0 =A0 =A0 static unsigned short crc_rg; // shiftregister > > =A0 =A0 =A0 =A0 crc_rg =3D crc_rg << 1; =A0 =A0 // leftshift 1 bit > > =A0 =A0 =A0 =A0 if((input & 1) ^ ((crc_rg>>14)&1)) =A0 =A0 =A0 =A0 > =A0 =A0 =A0 =A0 { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 crc_rg =3D crc_rg ^ 0x4599; > =A0 =A0 =A0 =A0 } > > =A0 =A0 =A0 =A0 crc_rg =3D crc_rg & 0x7fff; // only 15 bits > > =A0 =A0 =A0 =A0 return crc_rg; > > } >
Hi, This code is buggy I think. The input message bit should be XORed to bit 14 of the CRC register *before* it is shifted (so >>14 should be changed to >>15). Anyway, here is code that updates the CRC register for a whole input byte at once: static inline uint16_t crc_next(uint16_t crc, uint8_t data) { uint16_t eor; unsigned int i =3D 8; crc ^=3D (uint16_t)data << 7; do { /* This might produce branchless code */ eor =3D crc & 0x4000 ? 0x4599 : 0; crc <<=3D 1; crc ^=3D eor; } while (--i); return crc & 0x7fff; } Use it like this: uint16_t crc_reg =3D 0; crc_reg =3D crc_next(crc_reg, msg[0]); crc_reg =3D crc_next(crc_reg, msg[1]); =2E.. After crc_next has been called for all message bytes crc_reg will contain the correct CRC value of the message. Best regards, Danjel McGougan

The 2024 Embedded Online Conference