1

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

  • It looks like this function is designed to be called in a loop, e.g. over the 25 bytes. You will have to supply an initial crc, maybe 0, and then it returns the next crc given the next byte. At the end of 25 bytes, you have a final crc, which you should compare with the last 2 bytes of the packet, 26-7. – Erik Eidt Jul 6 at 15:25
  • oh, thats starting to make much more sense! I think it is the CRC16 CCIT algorithm that is used, so that would mean starting it off with passing it a zero, and then 'reinjecting' the answer each time until i'm done. The packet is stored in an array of bytes, so I will need to work out how to send the correct byte out from the loop (I dont think I am doing that properly at the moment) So effectively you process the first byte with the code, get the answer, then start the next byte's assessment with the answer from the last. I think I get it. – James Hounslow Jul 6 at 15:36
2

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.)

| improve this answer | |
  • I believe that it is CRC-16 CCIT 'Zero' so probably need to start it with 0x0 Memory is not an issue so will take a look at the table processing link you have given - many thanks – James Hounslow Jul 6 at 15:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.