Closed robsonoduarte closed 2 years ago
What you want to do is to calculate the CRC of a number representation in memory.
There are several problems to tackle
I'll post a minimal sketch asap
update: removed incorrect info from post.
a minimal function to get the right output.
void test()
{
char str[24] = "0x0105AA"; // AA0501 // NOTE add 0x for proper conversion
uint32_t number = strtoul(str, (char**)0, 0);
Serial.println(str);
Serial.println(number, HEX);
Serial.println(crc16((uint8_t *) &number, 3, 0x1021, 0xFFFF, 0xFFFF, true, true), HEX); // NOTE LENGTH 3
}
0x0105AA 105AA D550
Note this is not a solution, but I do not know how your input can change so I cannot write the function.
Gave it a try and came up with this function. Another point of attention popped up when reversing the string, you must swap 2 chars (= 1 byte) per iteration.
uint32_t crc_HEX(char *str)
{
// add 0x
char ws[10] = "0x";
// "reverse" string 2 digits per iteration
uint8_t len = strlen(str);
int j = 2;
for (int i = len - 1; i > 0;)
{
ws[j + 1] = str[i--];
ws[j] = str[i--];
j += 2;
}
ws[j] = 0;
Serial.println(ws);
// convert to number
uint32_t number = strtoul(ws, (char**)0, 0);
// CRC
uint32_t n = crc16((uint8_t *) &number, len / 2, 0x1021, 0xFFFF, 0xFFFF, true, true);
return n;
}
As this is rather specific code I won't make it part of the library yet. I did add the link of the online CRC calculator to the readme, so in the future it will be part of the release.
Hi @RobTillaart !
Thanks for the all answers ! and codes :rocket:
About your questions:
is it always HEX?
yes
is it always 3 bytes (6 digits)? think preceding zero's, will you get "00000F" or "0F" or even "F"
no
, we use the 11 bytes, a example of final string we will use 0xAA0D261001000000000F97
, the result of online calc is 692A
Should you reverse the string or reverse the bytes in number?
reverse
bytes in number
You can help us, to change your minimal function to use the 11Bytes ?
@robsonoduarte If you use 11 bytes for the code implies an integer of 88 bits ... The single call crc16() cannot handle that.
So you should create a CRC16 object, and "feed it byte by byte"
uint16_t crc_str(char * str)
{
CRC16 crc;
crc.setPolynome(0x1021);
crc.setStartXOR(0xFFFF);
crc.setEndXOR(0xFFFF);
crc.setReverseIn(true);
crc.setReverseOut(true);
int len = strlen(str);
int i = 0;
while (i < len)
{
char s[5] = "0x";
s[2] = str[i++];
s[3] = str[i++];
s[4] = 0;
uint32_t value = strtoul(s, (char**)0, 0);
crc.add(value);
Serial.print(s);
Serial.print("\t");
Serial.print(value, HEX);
Serial.print("\t");
Serial.println(crc.getCRC(), HEX);
}
}
you can probably speed up the creation of value from the initial string in the loop
Think the CRC16 object might need an extra constructor to set all parameters at once. (other issue)
Thanks for your help @RobTillaart !
The last code worked perfectly for our problem !
:rocket: :muscle: :heart:
if you have an optimized version for the function I'm interested for reference purposes.
Hi,
Have a possible to use the function
crc16
when the value to calculate is inHEX
?I am using this CRC calculation online to check the calc, when the content type is a
String
, the result is ok:using the crc function
:result by func
=>5E5A
online
:but we need the result in HEX
:result
=>D550
So, we not found in documentation if is possible to do that :eyes:
Thanks !