I need to implement CRC-8 with a specific polynomial of 32bit data. Here is my result from a transmitter:
Data:12586966
CRC-8: 22(0x16)
Polynomial:0x97
Initial data:0x00
No final XOR calculation
What is the algorithm to check the incoming data is equal to its CRC-8?
If the CRC is appended to the data, and there is no final XOR, then a recalculated CRC will be zero.
In hex, the 4 bytes of data are: 00 C0 0F D6. The CRC8 calculation effectively appends a 00 to create a dividend and generates the remainder using 197 as the divisor: {00 C0 0F D6 D6} % 197 = 16. Then the remainder is "subtracted" from the dividend, but in this case both addition and subtraction are the same, XOR, so the CRC is just appended to the data: {00 C0 0F D6 16}. Repeating the process with the appended CRC (and the implied appended 00), {00 C0 0F D6 D6 16 00} % 197 = 00.
Related
I'm trying to understand how a protocol works, it's from a TEC-Microsystem device (DX5100), it says:
CRC: Byte of the control sum CRC-8. It can be absent in some options
of the protocol. The control sum CRC-8 is calculated before the
stuffing for the entire packet, beginning with the byte FEND and
finishing with the last databyte. If a packet transmits an address,
when calculating the control sum, its true value is used, i.e. MSB=1
is not taken into account. For the calculation of the control sum the
polynomial is used. CRC = X8 + X5 + X4 + 1.
When I sniff the data being sent by their software, I see this data being transmitted:
0xC0 0x81 0x04 0x02 0x02 0x00 0x55
If a packet transmits an address,
when calculating the control sum, its true value is used, i.e. MSB=1
is not taken into account
This means that the data taken into account to compute the CRC is actually 0xC0 0x01 0x04 0x02 0x02 0x00 (second byte is 0x01 instead of 0x81).
According to what I could find on wikipedia, "CRC = X8 + X5 + X4 + 1" means they use "CRC-8-Dallas/Maxim".
However, when I use https://crccalc.com/, enter C00104020200 and hit "CALC-CRC-8" it reports 0x82 for "CRC-8/MAXIM", not 0x55. Am I missing something?
More examples from the sniffer:
C0 81 03 02 02 00 D3, so C0 01 03 02 02 00 CRC is D3
C0 81 05 02 02 00 DA, so C0 01 05 02 02 00 CRC is DA
With two examples, you can XOR them, which eliminates initial value and final xor, as if both were 00:
C0 01 03 02 02 00 CRC is D3
C0 01 05 02 02 00 CRC is DA
---------------------------
00 00 06 00 00 00 CRC is 09
This confirms that the CRC polynomial is 0x31 (reversed to 0x8C), input reflected, result reflected.
Using initial value 0xDE didn't work, so I tried reversing the bits to 0x7B which works for the three examples in the question. So initial value == 0x7B, the polynomial will also be bit reversed from 0x31 to 0x8C, but the online calculator uses the non-reversed polynomial, 0x31. If you click on "show reflected lookup table", calculate CRC, then look at row 8 byte 0, you will see the 0x8C.
I am trying to decode a 9-byte RS-485 packet that has a 3-byte CRC as shown below. Using a SW serial monitor I have decoded the parameter portion Using an online calculator.
I know can calculate Byte7 using 8-bit Checksum8 Modulo 256. My issue is
I cannot determine the last 2 Bytes of CRC.
I have attached my output from the reveng CRC decoder and it
finds a Model but not a name. I supplied 4 full 9 Byte packets.
reveng -w8 -sF 9BYTEPACKET1 9BYTEPACKET2 9BYTEPACKET3 9BYTEPACKET4
And as shown in the image link it returns:
width=8,poly=0x01,init=0x00,refin=false,refout=false,xorout=0x00,check=0x31,residue=0x00,name="(none)"
Sample Data:
00 32 2a ff ff cd 27 03 f1
00 20 03 ff ff cd ee 02 02
00 13 28 ff ff cd 06 03 f3
00 13 02 ff ff cd e0 02 3e
Byte1 = ID(Can Change)
Byte2 = Parameter(Can Change)
Byte3 = Parameter(Can Change)
Byte4 = 0xFF (Never changes)
Byte5 = 0xFF (Never changes)
Byte6 = 0xCD (Never changes)
Byte7 = Checksum8 Modulo 256 (I can calculate this from Byte1 to Byte6)
Byte8 = CRC (Changes with diff Parameter data)
Byte9 = CRC (Changes with diff Parameter data)
Any help would be appreciated.
Your Byte8 and Byte7 are simply the sum of the preceding bytes in little-endian order. Byte9 is then the exclusive-or of the preceding bytes.
There is no CRC.
I'm writing a code for Arduino C++.
I have a byte array with hex byte values, for example:
20 32 36 20 E0 EC 20 F9 F0 E9 E9 E3 F8 5C 70 5C 70 5C 73 20 E3 E2 EC 20 F8 E0 E5 E1 EF 20 39 31 5C
There are four ASCII digits in these bytes:
HEX 0x32 is number 2 in ascii code
HEX 0x35 is number 5 in ascii code
HEX 0x39 is number 9 in ascii code
and so on....
https://www.ascii-codes.com/cp862.html
So the hex values 32, 36 represent the number 26, and 39, 31 represent 91.
I want to find these numbers and reverse each group, so that (in this example) 62 and 19 are represented instead of 26 and 91.
The output would thus have to look like this:
20 36 32 20 E0 EC 20 F9 F0 E9 E9 E3 F8 5C 70 5C 70 5C 73 20 E3 E2 EC 20 F8 E0 E5 E1 EF 20 31 39 5C
The numbers don't have to be two digits but could be anything in 0-1000
I also know that each group of such numbers is preceded by the hex value 20, if that helps.
I have done this in C# (with some help of Stack overflow users :-) ):
string result = Regex.Replace(HexMessage1,
#"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)",
match => string.Join("-", Transform(match.Value.Split('-'))));
private static IEnumerable<string> Transform(string[] items)
{
// Either terse Linq:
// return items.Reverse();
// Or good old for loop:
string[] result = new string[items.Length];
for (int i = 0; i < items.Length; ++i)
result[i] = items[items.Length - i - 1];
return result;
}
Can someone help me make it work on C++?
Loop over the array, element by element, looking for 0x32 or 0x39. If found, check the next byte (if within bounds) to see if it matches 0x36 or 0x31 (respectively). If it does then swap the current and the next byte. Continue the loop, skipping over the current and the next byte.
Here is memory block I'm working with:
You can see 8b ff 55 8b ec 83 7d 0c 01 . . . . code. I want to get one each byte, so I tried:
DWORD offset; // this memroy has '0x61CAB0E4' and that means '8b ff 55... memroy block'
BYTE Result;
memcpy(&Result, &offset, 1); //1 mean byte as I want
BUT, the result is not correct. If I debug, the result value is 228 and I was expecting that value would be 8b.
How can I memory block one byte one?
8b,
ff,
55,
8b,
ec,
83,
7d,
....etc
These are the results:
You are not converting properly your result, and misinterpreting:
Your result is indeed decimal - 228.
In binary this is 11100100
The data is most likely stored in 2s complement in your P and depending on the endian and assuming the debugger just interpreted the binary as binary you get 10001011 - this is 139.
Finally, convert to two digit hex number: 1000 is 8, 1011 is 11 which is b, so finally 8b.
I'm attempting to mimic the function used for creating CRC's in PNG files, I'm using the autodin II polynomial and the source code from:
http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/crc32.c
My tests have all been for the IHDR chunk, so my parameters have been:
crc - 0xffffffff and 0 (both have been suggested)
buff - the address of the IHDR Chunk's type.
length - the IHDR Chunk's length + 4 (the length of the chunk's data + the length of the type)
I printed the calculated CRC in binary, which I compared to the actual CRC of the chunk. I can see no similarities (little-big endian, reversed bits, XOR'd, etc).
This is the data for the IHDR chunk (hexadecimal format):
length(big endian): d0 00 00 00 (13)
type: 49 48 44 52
data: 00 00 01 77 00 00 01 68 08 06 00 00 00
existing CRC: b0 bb 40 ac
If anyone can tell me why my calculations are off, or give me a CRC32 function that will work I would greatly appreciate it.
Thank-you!
The CRC-32 algorithm used in PNG images is described here: http://www.w3.org/TR/PNG-Structure.html#CRC-algorithm (there's also a link to C code for doing test calculations).
But as #Jigsore pointed out, you won't get sensible results from the data you posted here. You've given us a 4-byte type identifier and what looks like 7.5 bytes of data to follow it. There should be a total of 13 bytes according to the length header.
EDIT:
This works using the function from w3.org:
int main() {
char input[] = { 0x49,0x48,0x44,0x52,0x00,0x00,0x01,0x77,0x00,
0x00,0x01,0x68,0x08,0x06,0x00,0x00,0x00 };
printf("%08lx\n",crc(input,17));
return 0;
}
Output:
ac40bbb0