我目前正在寻找如何确定从机器到PC产生的CRC(反之亦然)。 设备使用串行通信或RS232电缆进行通信。
I do only have data to be able for us to create a program to be used for both devices.
The data given was from my boss and the program was corrupted. So we are trying for it to work out.
I hope everyone can help.
Thanks :)
答案 0 :(得分:2)
协议中用于CRC计算的序列是ASCII字符串
根据我们的CRC calculator
,这是一个具有以下规格的CRCCRC:16,1021,0000,0000,否,否
表示:
CRC width: 16 bit (of course)
polynomial: 1021 HEX (truncated CRC polynomial)
init value: 0000
final Xor applied: 0000
reflectedInput: No
reflectedOutput: No`
(如果'初始值'是FFFF,它将是“由CCITT指定的16位宽度CRC”)。
另请参阅Docklight CRC glossary和Boost CRC library有关CRC术语的含义以及示例代码。
我所做的是编写一个小脚本,在第一个简单的“REQ = INI”命令的不同部分上尝试流行的16位CRC,看看我是否最终得到4255的总和。这失败了,但是我不是试图通过尝试各种多样性来完全蛮力,而是认为它可能只是已知标准的一个奇怪的/有缺陷的实现,并且确实成功地使用了CRC-CCITT的变体。
Heres有点慢&简单的C代码(不是基于表的!)来计算各种CRC:
// Generic, not table-based CRC calculation
// Based on and credits to the following:
// CRC tester v1.3 written on 4th of February 2003 by Sven Reifegerste (zorc/reflex)
unsigned long reflect (unsigned long crc, int bitnum) {
// reflects the lower 'bitnum' bits of 'crc'
unsigned long i, j=1, crcout=0;
for (i=(unsigned long)1<<(bitnum-1); i; i>>=1) {
if (crc & i) crcout|=j;
j<<= 1;
}
return (crcout);
}
calcCRC(
const int width, const unsigned long polynominal, const unsigned long initialRemainder,
const unsigned long finalXOR, const int reflectedInput, const int reflectedOutput,
const unsigned char message[], const long startIndex, const long endIndex)
{
// Ensure the width is in range: 1-32 bits
assert(width >= 1 && width <= 32);
// some constant parameters used
const bool b_refInput = (reflectedInput > 0);
const bool b_refOutput = (reflectedOutput > 0);
const unsigned long crcmask = ((((unsigned long)1<<(width-1))-1)<<1)|1;
const unsigned long crchighbit = (unsigned long)1<<(width-1);
unsigned long j, c, bit;
unsigned long crc = initialRemainder;
for (long msgIndex = startIndex; msgIndex <= endIndex; ++msgIndex) {
c = (unsigned long)message[msgIndex];
if (b_refInput) c = reflect(c, 8);
for (j=0x80; j; j>>=1) {
bit = crc & crchighbit;
crc<<= 1;
if (c & j) bit^= crchighbit;
if (bit) crc^= polynominal;
}
}
if (b_refOutput) crc=reflect(crc, width);
crc^= finalXOR;
crc&= crcmask;
return(crc);
}
通过上面列出的此代码和CRC规范,我能够重新计算以下三个示例CRC:
10.03.2014 22:20:57.109 [TX] - REQ=INI<CR><LF>
<RS>CRC=4255<CR><LF>
<GS>
10.03.2014 22:20:57.731 [TX] - ANS=INI<CR><LF>
STATUS=0<CR><LF>
<RS>CRC=57654<CR><LF>
<GS>
10.03.2014 22:20:59.323 [TX] - ANS=INI<CR><LF>
STATUS=0<CR><LF>
MID="CTL1"<CR><LF>
DEF="DTLREQ";1025<CR><LF>
INFO=0<CR><LF>
<RS>CRC=1683<CR><LF>
<GS>
我在DEF=
部分的非常复杂的部分失败了 - 可能没有正确理解字符序列。
我曾经使用Docklight脚本对此进行逆向工程:
Sub crcReverseEngineer()
Dim crctypes(7)
crctypes(0) = "CRC:16,1021,FFFF,0000" ' CCITT
crctypes(1) = "CRC:16,8005,0000,0000" ' CRC-16
crctypes(2) = "CRC:16,8005,FFFF,0000" ' CRC-MODBUS
' lets try also some nonstandard variations with different init and final Xor, but stick
' to the known two polynoms.
crctypes(3) = "CRC:16,1021,FFFF,FFFF"
crctypes(4) = "CRC:16,1021,0000,FFFF"
crctypes(5) = "CRC:16,1021,0000,0000"
crctypes(6) = "CRC:16,8005,FFFF,FFFF"
crctypes(7) = "CRC:16,8005,FFFF,0000"
crcString = "06 1C 52 45 51 3D 49 4E 49 0D 0A 1E 43 52 43 3D 30 30 30 30 0D 0A 1D"
For reflectedInOrOut = 0 To 3
For cType = 0 To 7
crcSpec = crctypes(cType) & "," & IIf(reflectedInOrOut Mod 2 = 1, "Yes", "No") & "," & IIf(reflectedInOrOut > 1, "Yes", "No")
For cStart = 1 To 3
For cEnd = 9 To (Len(crcString) + 1) / 3
subDataString = Mid(crcString, (cStart - 1) * 3 + 1, (cEnd - cStart + 1) * 3)
result = DL.CalcChecksum(crcSpec, subDataString, "H")
resultInt = CLng("&h" + Left(result, 2)) * 256 + CLng("&h" + Right(result, 2))
If resultInt = 4255 Then
DL.AddComment "Found it!"
DL.AddComment "sequence: " & subDataString
DL.AddComment "CRC spec: " & crcSpec
DL.AddComment "CRC result: " & result & " (Integer = " & resultInt & ")"
Exit Sub
End If
Next
Next
Next
Next
End Sub
Public Function IIf(blnExpression, vTrueResult, vFalseResult)
If blnExpression Then
IIf = vTrueResult
Else
IIf = vFalseResult
End If
End Function
希望这有帮助,我很乐意提供额外信息或澄清细节。