c#中的CRC-ITU计算 [英] CRC-ITU calculation in c#

查看:72
本文介绍了c#中的CRC-ITU计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new to C#. I need to calculate CRC-ITU for the packet recieved from GPS devices. There is C code provided in the documentation but i don't know how to port it to C#, anyone could help me?

这是C语言中的CRC-ITU算法:

here is CRC-ITU algorithm in C :

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/中找到了C#代码1656947.html ,但我不知道如何使用它,这是代码

I've also found C# code from http://ppcode.blogbus.com/logs/1656947.html but I don't know how to use it, here's the code

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);
  }

 }

这是文档中的一些示例:

here is some example in the documentation :

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

full packet : 0x78 0x78 0x0D 0x01 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45 0x00 0x01 0x8C 0xDD 0x0D 0x0A

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

Start bit : 0x78 0x78 lenght : 0x0D Protocol No. : 0x01 Device ID : 0x01 0x23 0x45 0x67 0x89 0x01 0x23 0x45 Serial No. : 0x00 0x01 CRC Verify : 0x8C 0xDD Stop Bit : 0x0D 0x0A

引用文档:

设备或服务器可以使用识别码判断接收到的数据的准确性.有时,由于电子噪音或其他干扰,数据在传输过程中会有所变化.在这种情况下,识别代码可以确保核心或关联核心对此类错误数据不做任何事情,这将增强系统的安全性和效率.该识别码采用CRC-ITU识别方法.协议中的CRC-ITU值从包装长度"到信息序列号"(包括包装长度"和信息序列号").如果接收器收到CRC错误的计算信息,则将其忽略并丢弃此数据包.

Device or server can judge the accuracy of data received with identifying code. Sometimes, because of the electronic noise or other interference, data will be changed a little in the transit process. In this case, identifying code can make sure the core or associated core do nothing with such kind of wrong data, which will strengthen the security and efficiency of system. This identifying code adopts CRC-ITU identifying method. The CRC-ITU value is from "Package Length' to "Information Serial Number" in the protocol (including "Package Length" and "Information Serial Number "). If the receiver receives CRC wrong calculating information, then ignore it and discard this data package.

因此,有人知道如何从上述示例中获取crc值吗?

So anyone have idea how to get crc value from above example? thx

推荐答案

只需遵循文档中的说明

协议中的CRC-ITU值从包装长度"到信息序列号"(包括包装长度"和信息序列号").

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

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

So we take the data from length to serial number

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

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

now we use those set of numbers and pass it in to the CRC function. The code you linked uses unsafe pointers, I don't know if you need them or not as you did not post any of where you are using it. If you have the data in a byte array you can re-write the function to just pass in the byte array instead of the pointer, then the code will no longer need to be marked unsafe.

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

Here is my cleaned up version that uses bytes

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似乎存储在大字节序中,而C#代码将产生小字节序.因此,在比较它们之前,需要翻转CRC的两个字节.

It appears that the CRC in the packet is stored in big Endian and C# code will produce little endian. So you will need to flip the two bytes of the CRC before you compare them.

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

As a side-note, I think that the IsCrcITUGood method is not from the gps spec. I think whatever you pulled this code example from had a special set of bytes to make the CRC always equal 0xF0B8. In your data it gives you the expected CRC value. I could find no way to make the CRC equal 0xF0B8

这篇关于c#中的CRC-ITU计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆