Domanda

I am trying to process some serial data (sent over UART). Its coming from a radio controlled receiver, is 27 bytes long. The last 2 bytes of this are a 16bit CRC check according to the spec.

The checksum is derived from the preceding 25 bytes

Along with the protocol there is this information on the checksum calculation:

 u16 CRC16(u16 crc, u8 value)
 {
     u8 i;
     crc = crc ^ (s16)value<<8;
     for(i = 0; i < 8; i++)
     {
         if(crc & 0x8000)
             crc = crc << 1^0x1021;
         else
             crc = crc << 1;
     }
     return crc;
 }

I have had to do a little 'translation' of this, as I am using an STM32 microcontroller, and the variables need to be declared a little different (uint16_t instead of u16 for example).

That said I think I have got completely the wrong end of the stick anyway.....

The code above appears to 'only' process a single byte of data, passed to the function in variable 'value'

It appears to also want a 16bit integer named 'crc' passed to it, which is where the confusion started......

I have the 27 byte packet of data. I have converted the last 2 bytes into the 16 bit checksum and have made sure that I have the endianness of this correct (the message is big endian, the stm32 is little endian, so you cant do a memcpy, you need to do a bit of bit shifting).

But how do I now get an answer as to whether the preceding 25 bytes of data have been received correctly.

Any help gratefully received. I've googled and read and just got myself more confused....

Many thanks

James

È stato utile?

Soluzione

This is apparently the CCITT CRC-16, and you might find implementation ideas here: https://stackoverflow.com/questions/21252069/ccitt-crc-16-bit-start-value-0xffff

The main point is that the function you cite processes one byte, this may be suitable when you can't buffer the whole message due to resource constraints. If you have all the bytes in a buffer, it makes more sense to embed the calculation into a loop over the buffer as in the referenced SO answer. You need to initialize the crc variable with 0xFFFF to get the correct result.

If you want to trade memory for speed, there are table-driven CRC-16 algorithms which process one byte at a time without a bit-processing loop. See https://stackoverflow.com/questions/22432066/how-to-use-table-based-crc-16-code for an example (note that it uses a different polynomial than your example, so you'd need a different precalculated table, I'm certain you can find one on the internet.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top