Achieving the correct CRC value

Hi all !!!!

Some time ago I found this piece of code for calculating CRC-32 on: http://excamera.com/sphinx/article-crc.html

I tested the code by finding the CRC of 'HELLO' as it is indicated in the example on the webpage and confirmed that it works by finding the same result as the webpage. Then I tried to use this code to find the CRC of a longer array using my Uno as indicated in the code bellow:

unsigned char sample[90] = {
  0x82, 0x81, 0x80, 0x30, 0, 0, 0, 0, 0x21, 0x46, 0x01, 0x1D, 0, 0, 0, 0, 0x3F, 0x01, 0x22, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0E, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0x0F, 0x4C, 0x82, 0x80, 0, 0, 0, 0x05, 0x01, 0xC1, 0x13, 0x1D, 0, 0, 0, 0, 0x3F, 0x01, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0xFA, 0, 0, 0x27
};
// sample : 828180300000214611D00003F1222206000000000000080E0000FA0027857F4C828000051C1131D00003F122060000000000000800000FA0027



static PROGMEM prog_uint32_t crc_table[16] = {
  0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 
  0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 
  0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 
  0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};

unsigned long crc_update(unsigned long crc, byte data)
{
  byte tbl_idx;
  tbl_idx = crc ^ (data >> (0 * 4));
  crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  tbl_idx = crc ^ (data >> (1 * 4));
  crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  return crc;
}

unsigned long crc_string( unsigned char *s)
{
  unsigned long crc = ~0L;
  while (*s)
    crc = crc_update(crc, *s++);
  crc = ~crc;
  return crc;
}


void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); 


  Serial.print(crc_string(sample), HEX); //gives 9BB978FC
}

void loop() // run over and over
{
}

It produced 9BB978FC as my CRC byte. Then I tried using this webpage which previously had produced reliable CRC bytes for me before: http://www.lammertbies.nl/comm/info/crc-calculation.html I got 430F8AB5.

I am not really sure if the code that I am compiling on Uno is interpreting my sample array as a big hexadecimal value or how I can get it to do so. Of course it is important for me to make sure that the array is not analyzed as an ASCII string, but as a hexadecimal value.

I totally appreciate any help and thank you in advanced. :)

as my CRC byte. Then I tried using this webpage which previously had produced reliable CRC bytes for me before: http://www.lammertbies.nl/comm/info/crc-calculation.html

Two things: 1) that's not a byte 2) do you know what polynomial is being used in each case?

There are many, many different types of CRC calculations, with results of different lengths. You would probably get more useful advice if you told us what it is you want to do with the CRC.

Two things: 1) that's not a byte 2) do you know what polynomial is being used in each case?

1) I apologize for referring to those 4 bytes as a byte. I must have been thinking of something else when I wrote that part. 2) Yes. The polynomial is :

0x04C11DB7

which is used for finding the CRC-32 that I am after.

There are many, many different types of CRC calculations, with results of different lengths. You would probably get more useful advice if you told us what it is you want to do with the CRC.

Let's say if I were to receive four CRC-32 bytes at the end of that "sample" array from a device using a Mega' Then I would want to calculate the CRC-32 of the "sample" and compare it with the CRC sent from that device to check for corrupted data. I just really want to know how I can get four correct CRC bytes using the function that I posted and confirm that the function is working fine. I do not understand why it is not functioning the way I thought it would.

If you guys know an easier or more efficient way to get the CRC-32, please let me know.

Cheers!!! :)

That algorithm does work, I used it here in my Base64 stream ( or a very similar version ):

http://forum.arduino.cc/index.php?topic=202336.0

You can use it to calculate the CRC while the data is incoming via a Stream ( Serial, Ethernet, SD ). Using it bidirectionally, you can calculate the outgoing CRC, then compare to the received CRC.

There are many flavors of CRC-32. They use different polynomials, different starting and ending conditions ("initial XOR or final XOR") and the direction of calculation can be forward or reverse. If you pick one particular implementation of CRC-32 and use it for all your calculations, you will have a good internal check for data transmission errors. However, to compare the results of your CRC-32 calculation to those of someone else's requires that you both make the same choices for polynomial, initial values, etc

In short there is no "correct CRC value". For more info, there are lots of overviews on the web.

I find this really interesting guys, thanks for following up so far. However, I had something interesting in mind, but I am not sure about it. See how pYro_65 mentioned:

That algorithm does work, I used it here in my Base64 stream ( or a very similar version ):

http://forum.arduino.cc/index.php?topic=202336.0

You can use it to calculate the CRC while the data is incoming via a Stream ( Serial, Ethernet, SD ). Using it bidirectionally, you can calculate the outgoing CRC, then compare to the received CRC.

I implemented his code on the "sample" array in my code and I got this:

OUT CRC: A1C82A16
IN CRC: A1C82A16

That is the result that I get for CRC-32 from: http://www.lammertbies.nl/comm/info/crc-calculation.html

When I enter the "sample" array and tell the web interface to interpret my array as an ASCII array. However, the four CRC-32 bytes that I receive from my particular device, treats "sample" as a big hex number not an ASCII string. I know this because, I used one of the data samples that the device sent me and calculated the four CRC-32 bytes using the above webpage and I clicked on the option that treats my array as a hex string. I got the same four bytes as the device had sent along with the array of data.

So....I am yet to find a CRC-32 code, that suits my purpose and I used the above website as a reference, because whatever method it is using, it provided me with the same CRC bytes that my device did. I suggest you have a look at that website and put the "sample" array and let me know if my understanding of what is happening is correct or not. Considering that I have been playing with CRC for a while and feel quite confused, I really appreciate your support and I apologize for my rookie mistakes. :sweat_smile: :)

Think of the representations this way:

My data: AABBCCDDEEFF

  • As an ascii representation it is 12 characters.
[A] [A] [B] [B] [C] [C] [D] [D] [E] [E] [F] [F]
  • Read as a hexidecimal value gives 6 bytes, ( two hex nibbles per byte )
[AA] [BB] [CC] [DD] [EE] [FF]

Interesting!! Also, if you checked that website, you would see that interpreting the array as Hex or ASCII produce different CRC-32 values. So any ideas or hints on how I can incorporate that into the CRC function that I am using or the one that you mentioned before?? :D

Yes, they will produce different values as there is half the amount of data being CRC’d in the HEX version.

o any ideas or hints on how I can incorporate that into the CRC function that I am using or the one that you mentioned before??

Why?

Search google for a hex string to integer code. However the conversion may be more costly than simply CRCing the whole array. Raw byte CRC’s won’t do?. The hex has no significance really, it just means you can only use characters in the range [0-9],[a-f].

My CRC stream uses the Print library so send it whatever data you like, ascii, integers, … It calculates the CRC off the raw bytes going through it.

Cheers!!! :D I will try to fit it in my code and let you know how it goes.