0

I need to send a string followed by its CRC8, 0x31 polynomial (= X^8 + X^5 + X^4 + 1), I've coded this successfully after some troubles, but it doesn't seem to work properly when I check the results. I used some online CRC calulators so check if my results are fine, but I don't get the same results, no matter what I try.

In fact, differents CRC calculators are not giving me the same results, which troubles me... Here are my trials on online CRC calculators, always using : CRC8, polynomial 0x31, data = TEMPS; (beginning of my string)

On http://www.sunshine2k.de/coding/javascript/crc/crc_js.html : enter image description here

On https://www.lddgo.net/en/encrypt/crc : enter image description here

On http://zorc.breitbandkatze.de/crc.html : enter image description here

It doesn't seem normal to get different results when the entry parameters are the same, it confuses me a lot. Am I missing something ?

No matter what I try, I don't get any of these results with my own code. Here is my code about CRC calculation, using RobTillaart's CRC library (https://github.com/RobTillaart/CRC):

   String crcData = "TEMPS;";
  int crcDataLength = crcData.length();
  char arrayForCrc[crcDataLength+1];
  crcData.toCharArray(arrayForCrc, crcDataLength+1);
  
  crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

The hex result of this code sample is 0xBA (186 decimal) I verified every input parameters with gets and prints, they're all correct :

arrayForCrc = "TEMPS;" polynomial = 0x31 StartXOR = 0 EndXOR=0 ReverseIn=false ReverseOut=false

Help would be greatly appreciated as I'm stuck and don't know what to try anymore. Thank you :)

3
  • 1
    I could explain it if you were getting 0xB5 but not 0xBA. It helps to have completely compilable code.
    – timemage
    Sep 30, 2022 at 23:45
  • I just filled out your code with guesses to the point where it compiled with the latest version of that library and I have it is printing 0xB5 and not 0xBA. So either we're both confused or you've got the wrong number in your question.
    – timemage
    Sep 30, 2022 at 23:56
  • Check your sunshine screenshot again, because if I put exactly what you have into it and calculate I don't get 0x6E; I get the expected 0x49. Regarding the 'lddgo' screenshot test, it's not really valid. The reverse settings are on. Once you get 0x49 correctly on the sunshine one, turn on both reflect options and you'll see you now get a 0x73 that matches what you have in the lddgo one. So, I'd remove it because this has nothing to do with the problem you're having with the library.
    – timemage
    Oct 1, 2022 at 0:41

1 Answer 1

2

The hex result of this code sample is 0xBA (186 decimal)

Not so far as I can tell; it's 0xB5, which is expected for a simple reason that you'll see. And when modified slightly it matches the 0x49 value. I'm inclined to trust that your code is correct, so far as you've shown it, but your report of what's doing is not correct.

I verified every input parameters with gets and prints, they're all correct

Well, no. As I mentioned in a comments on the question, I get the expected 0x49 on the first site you mentioned with the correct settings. I'm not sure why you're showing 0x6E. But guess what happen if I hit enter after "TEMPS;"? 0x6E. The newline character matters. Also, I do get a 0xBA if I use the correct input but fail to set CRC8 to custom and change 0x07 to a 0x31 in the polynomial. So, maybe that's how you found that value.

If you switch to bytes mode the site expects a sequence of character code values and ignores whitespace (apart from treating it as a delimiter). You can put 0x54 0x45 0x4d 0x50 0x53 into it in bytes mode to see 0x49 result also. You can then add 0x0D (newline) to see it to result in a 0x6E from before.

Regarding the middle site, the settings aren't correct (the reverse setting is on for input and output) and I don't see how to make them correct; they don't seem to have a custom option. However, you can turn on the reflect options on the first site to get the same result as in the 2nd site in order to convince yourself that is what is going on. The third site's output is correct for what you've put into it. It just doesn't match what you're code is actually doing.

Your basic problem is the +1 in this line:

crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);

You've included the null terminator in the calculation. This is 7 bytes: 'T', 'E', 'M', 'P', 'S', ';', '\0'. These websites just aren't doing that; they are not automatically adding a null terminator at the end of whatever you type in string mode. Alternately, if you wanted the null terminator in the CRC calculation, your code is fine, but you're going to need to switch to HEX input mode on the website and enter a 0x00 into it after the hex values for the other characters in TEMPS; so as to match. And it will match, I've tested this. You can also: put the first site into bytes mode and put "0x54 0x45 0x4d 0x50 0x53 0x3b 0x00" into it and you will see it now produces a 0xB5, like your current code.

Otherwise, you just need to not enter the null terminator into the calculation:

crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);

This will result in 0x49 coming out of crcTrame.getCRC() instead of 0xB5:

#include "CRC8.h"

void setup() {
  Serial.begin(9600);
}

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();
  char arrayForCrc[crcDataLength+1];
  crcData.toCharArray(arrayForCrc, crcDataLength+1);

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}

If you also want to sanity check what happened with the 0x6E output earlier, you can then change crcData to String crcData = "TEMPS;\n" (adding the newline) and watch it start printing 6E.


There's a .getBytes() function in String that is pretty much what you have without needin the cast:

crcTrame.getBytes(arrayForCrc, crcDataLength);

I'm not sure if you have a good reason for "TEMPS;" to begin life in a String or then to have to get it into an character array. If you're only doing this so you can then call crcTrame.add(), well, you needn't:

#include "CRC8.h"

void setup() {
  Serial.begin(9600);
}

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add(
    (const uint8_t *)crcData.c_str(),
    crcData.length() // <- Does not count null terminator.
  );
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}

Note: I'm only creating stringCrc to mirror what you were doing. Here, it could just as easily be Serial.println(crcTrame.getCRC(), HEX); and potentially in whatever context you're doing it in. The cast can also be done in a more C++ approved (though uglier way with crcTrame.add(reinterpret_cast<const uint8_t *>(crcData.c_str()), crcData.length());

Any sequence of any number of add() calls that delivers the same data in the same order into calculation will yield the same CRC. There's also an overload of add() that takes an individual character without needing to involve a pointer at all. So your data doesn't need to come from a String, nor be a null-terminated string, or character array, nor fit entirely in memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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