gpt4 book ai didi

c# - c#中的CRC-ITU计算

转载 作者:行者123 更新时间:2023-11-30 13:49:08 25 4
gpt4 key购买 nike

我是 C# 新手。我需要为从 GPS 设备收到的数据包计算 CRC-ITU。文档中提供了 C 代码,但我不知道如何将其移植到 C#,有人可以帮助我吗?

这里是 CRC-ITU 算法:

static const U16 crctab16[] = 
{
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
};

// calculate 16 bits CRC of the given length data.
U16 GetCrc16(const U8* pData, int nLength)
{
U16 fcs = 0xffff; // Initialize

while(nLength>0){
fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
nLength--;
pData++;
}
return ~fcs; // Negate
}

// Check whether the 16 bits CRC of the given length data is right.
BOOL IsCrc16Good(const U8* pData, int nLength)
{
U16 fcs = 0xffff; // Initialize
while(nLength>0){
fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
nLength--;
pData++;
}
return (fcs == 0xf0b8); // 0xf0b8 is CRC-ITU的"Magic Value"
}

我还从 http://ppcode.blogbus.com/logs/1656947.html 中找到了 C# 代码但我不知道怎么用,这是代码

public class CrcITUTable
{
static ushort [] crctab16 =
{
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
};

public CrcITUTable()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

unsafe public ushort GetCrcITU_T(byte * pData,int nLength,out string crcCode)
{
ushort fcs=0xFFFF;
ushort uRlt;
string strTmp;
while(nLength>0)
{
fcs= (ushort) ((ushort)(fcs>>8)^ crctab16[(fcs ^ *pData) &0xFF ]);
nLength--;
pData++;
}

uRlt=(ushort)~fcs;
strTmp=uRlt.ToString("X4") ;
crcCode=strTmp.Substring(2,2) + " " + strTmp.Substring(0,2);

return uRlt;
}

unsafe public bool IsCrcITUGood_T(byte * pData,int nLength)
{
ushort fcs=0xFFFF;
while(nLength>0)
{
fcs= (ushort) ((ushort)(fcs>>8)^ crctab16[(fcs ^ *pData) &0xFF ]);
nLength--;
pData++;
}

return (fcs==0xF0B8);
}

}

这是文档中的一些示例:

完整数据包:0x78 0x78 0x0D 0x01 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45 0x00 0x01 0x8C 0xDD 0x0D 0x0A

起始位:0x78 0x78长度:0x0D协议(protocol)号:0x01设备 ID:0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45序列号:0x00 0x01CRC 验证:0x8C 0xDD停止位:0x0D 0x0A

引用自文档:

设备或服务器可以通过识别码判断接收到的数据的准确性。有时,由于电子噪声或其他干扰,数据在传输过程中会发生少许变化。在这种情况下,识别码可以确保核心或关联核心对此类错误数据不做任何处理,从而增强系统的安全性和效率。该识别码采用CRC-ITU识别方法。 CRC-ITU值是从协议(protocol)中的“Package Length”到“Information Serial Number”(包括“Package Length”和“Information Serial Number”)。如果接收方收到CRC错误计算信息,则忽略并丢弃该数据包。

所以有人知道如何从上面的示例中获取 crc 值吗?谢谢

最佳答案

按照文档的说明进行即可

The CRC-ITU value is from "Package Length' to "Information Serial Number" in the protocol (including "Package Length" and "Information Serial Number ").

所以我们把数据从长度取到序号

0x0D 0x01 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45 0x00 0x01

现在我们使用这些数字集并将其传递给 CRC 函数。您链接的代码使用了不安全的指针,我不知道您是否需要它们,因为您没有在使用它的地方发布任何内容。如果数据位于字节数组中,则可以重写函数以仅传入字节数组而不是指针,这样代码将不再需要标记为不安全。

这是我使用字节的清理版本

static void Main(string[] args)
{
byte[] dataPacket = { 0x78, 0x78, 0x0D, 0x01, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x00, 0x01, 0x8C, 0xDD, 0x0D, 0x0A };
var crc16 = GetCrc16(dataPacket, 2, 12);

if (crc16 == ReadBigEndianUInt16(dataPacket, 14)))
{
Debugger.Break();
//use packet.
}

Debugger.Break();
}

public static UInt16 ReadBigEndianUInt16(byte[] data, int offset)
{
if(BitConverter.IsLittleEndian == true)
{
var bytes = new byte[2] {data[offset+1], data[offset]}
return BitConverter.ToUInt16(bytes, 0);
}
else
{
return BitConverter.ToUInt16(data, offset);
}
}

public static ushort GetCrc16(byte[] data, int offset, int length)
{
ushort fcs = 0xFFFF;
for (int i = offset; i < length + offset; i++)
{
fcs = (ushort)((ushort)(fcs >> 8) ^ crctab16[(fcs ^ data[i]) & 0xFF]);
}

return (ushort)(~fcs);
}

public static bool IsCrcITUGood(byte[] data, int offset, int length)
{
ushort fcs = 0xFFFF;
for (int i = offset; i < length + offset; i++)
{
fcs = (ushort)((ushort)(fcs >> 8) ^ crctab16[(fcs ^ data[i]) & 0xFF]);
}

return (fcs == 0xF0B8); //magic value
}

static ushort[] crctab16 = /*(snip)*/;

数据包中的 CRC 似乎存储在 big Endian 中,而 C# 代码将生成 little endian。因此,在比较它们之前,您需要翻转 CRC 的两个字节。


作为旁注,我认为 IsCrcITUGood 方法不是来自 gps 规范。我认为无论您从中提取此代码示例,都有一组特殊的字节,以使 CRC 始终等于 0xF0B8。在您的数据中,它为您提供了预期的 CRC 值。我找不到使 CRC 等于 0xF0B8

的方法

关于c# - c#中的CRC-ITU计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10167461/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com