我正在尝试编写一个用于串行端口通信的程序,在这里我需要使用CRC发送数据包,我正在用C#语言编写此代码。
下面是接收机期望具有CRC的样本数据包。
10 02 B1 F0 3F 32 08 00 00 10 03 B4 5C
第二个数据包:10 02 B1 F0 3F 32 07 00 00 10 03 4D EE
10-DLE代码
02-STX
B1 F0 3F 32 08 00 00是数据
10-DLE
03 -ETX
B4-CRC下拜
5C-CRC-上拜
CCIT : (Fx) = x16 + x12 + x5 + 1
操作初始值:FFFFH
我尝试了一些在线CRC计算器,但到目前为止还算不上运气,有人可以指导如何为上述数据(B1 F0 3F 32 08 00 00)计算CRC吗?可能可以建议在线计算器,它可以为我提供以上的输出(B4 5C)
。
感谢您的指教!
答案 0 :(得分:1)
我发现了一些可行的方法,但似乎有些奇怪。
首先我将两个样本进行了异或
10 02 B1 F0 3F 32 08 00 00 10 03 B4 5C
10 02 B1 F0 3F 32 07 00 00 10 03 4D EE
--------------------------------------
00 00 00 00 00 00 0F 00 00 00 00 F9 B2
这消除了初始CRC和最终xor值,并导致使用了0x11021 CRC反映的位。看来CRC正在使用8个字节的数据,包括结尾的0x10。
使用下面链接的CRC计算器,选择任何CRC16,然后单击“自定义”并将参数设置为:输入反射选中,输出反射选中,poly = 0x1021。没有足够的信息来确定初始值和最终异或值,而没有不同大小的消息。使用8个字节的数据,一些示例选项为:初始值= 0x5B08,最终异或值= 0x0000,或初始值= 0xffff,最终异或值= 0xdde5,或初始值= 0x0000,最终异或值= 0xa169。
使用反射参数时,计算器位将初始化值反转(0x5B08为0x17DA反转位)。对于代码,这3个组合是{0x17da,0x0000},(0xffff,0xdde5},{0x0000,0xa169}。poly = 0x8408并向右移动。
我用xx表示数据过高
xx xx B1 F0 3F 32 08 00 00 10 xx B4 5C
xx xx B1 F0 3F 32 07 00 00 10 xx 4D EE
由于前两个字节为{10 02},因此可以通过更改初始值来包含固定值。但是,我无法包含ETX 03值。
答案 1 :(得分:0)
我在网络上找到了第二个热门歌曲,但我将其内容复制到此处以供参考:
using System;
public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }
public class Crc16Ccitt {
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0;
public ushort ComputeChecksum(byte[] bytes) {
ushort crc = this.initialValue;
for(int i = 0; i < bytes.Length; ++i) {
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes) {
ushort crc = ComputeChecksum(bytes);
return BitConverter.GetBytes(crc);
}
public Crc16Ccitt(InitialCrcValue initialValue) {
this.initialValue = (ushort)initialValue;
ushort temp, a;
for(int i = 0; i < table.Length; ++i) {
temp = 0;
a = (ushort)(i << 8);
for(int j = 0; j < 8; ++j) {
if(((temp ^ a) & 0x8000) != 0) {
temp = (ushort)((temp << 1) ^ poly);
} else {
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}