C# CRC 实现

发布于 2024-10-18 07:20:08 字数 448 浏览 6 评论 0原文

我正在尝试将串行端口设备集成到我的应用程序中,该应用程序需要对我发送给它的字节进行 CRC-CCTT 验证。 我对管理字节数据包有点陌生,需要帮助。

它使用以下公式进行 CRC 演算:

[CRC-CCITT P(X)= X16 + C12 + C8 + 1]

例如,对于数据包:0xFC 0x05 0x11,CRC 为 0x5627。 然后我将此数据包发送到设备: 0xFC 0x05 0x11 0x27 0x56

另外,数据包长度将从 5 到 255 不等(包括 CRC 检查字节)

我不知道如何实现这一点,所以欢迎任何想法/建议。

希望我说清楚了, 提前致谢。

编辑: 这是我需要做的规范:

在此处输入图像描述

I am trying to integrate a Serial-port device into my application, which needs CRC-CCTT validation for the bytes that I send to it.
I'm kinda new into managing byte packets, and need help for this.

It uses this formula for making the CRC calculus:

[CRC-CCITT P(X)= X16 + C12 + C8 + 1]

So for example for the packet: 0xFC 0x05 0x11, the CRC is 0x5627.
Then I send this packet to the device: 0xFC 0x05 0x11 0x27 0x56

Also, packet lenghts will vary from 5 to 255 (including CRC checks bytes)

I don't know how to implement this, so any idea/suggestions will be welcome.

Hope I made myself clear,
Thanks in Advance.

EDIT:
here is the specification of what I need to do:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

暖风昔人 2024-10-25 07:20:08

标准 crc-ccitt 是 x16 + x12 + x5 + 1 我写了一个 @ http://www.sanity-free .com/133/crc_16_ccitt_in_csharp.html 如果我有时间,我会看看是否无法修改它以与 x16 + x12 + x8 + 1 多边形一起运行。

编辑:

给你:

public class Crc16CcittKermit {
    private static ushort[] table = {
      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 static ushort ComputeChecksum( params byte[] buffer ) {
        if ( buffer == null ) throw new ArgumentNullException( );
        ushort crc = 0;
        for ( int i = 0; i < buffer.Length; ++i ) {
            crc = (ushort)( ( crc >> 8 ) ^ table[( crc ^ buffer[i] ) & 0xff] );
        }
        return crc;
    }

    public static byte[] ComputeChecksumBytes( params byte[] buffer ) {
        return BitConverter.GetBytes( ComputeChecksum( buffer ) );
    }
}

示例:

ushort crc = Crc16CcittKermit.ComputeChecksum( 0xFC, 0x05, 0x11 );
byte[] crcBuffer = Crc16CcittKermit.ComputeChecksumBytes( 0xFC, 0x05, 0x11 )
// crc = 0x5627
// crcBuffer = { 0x27, 0x56 }

standard crc-ccitt is x16 + x12 + x5 + 1 I wrote the one @ http://www.sanity-free.com/133/crc_16_ccitt_in_csharp.html If I have time I'll see if I can't modify it to run with the x16 + x12 + x8 + 1 poly.

EDIT:

here you go:

public class Crc16CcittKermit {
    private static ushort[] table = {
      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 static ushort ComputeChecksum( params byte[] buffer ) {
        if ( buffer == null ) throw new ArgumentNullException( );
        ushort crc = 0;
        for ( int i = 0; i < buffer.Length; ++i ) {
            crc = (ushort)( ( crc >> 8 ) ^ table[( crc ^ buffer[i] ) & 0xff] );
        }
        return crc;
    }

    public static byte[] ComputeChecksumBytes( params byte[] buffer ) {
        return BitConverter.GetBytes( ComputeChecksum( buffer ) );
    }
}

sample:

ushort crc = Crc16CcittKermit.ComputeChecksum( 0xFC, 0x05, 0x11 );
byte[] crcBuffer = Crc16CcittKermit.ComputeChecksumBytes( 0xFC, 0x05, 0x11 )
// crc = 0x5627
// crcBuffer = { 0x27, 0x56 }
人海汹涌 2024-10-25 07:20:08

哈哈,我遇到了完全相同的状态请求序列,我目前正在开发与 CashCode Bill Validator 一起使用的软件:)。这是对我有用的代码,它是 CRC16-CCITT,其反转多项式等于 0x8408(代码中的 BDPConstants.Polynomial)。这就是对我有用的代码:

    // TableCRC16Size is 256 of course, don't forget to set in somewhere
    protected ushort[] TableCRC16 = new ushort[BDPConstants.TableCRC16Size];
    protected void InitCRC16Table()
    {
        for (ushort i = 0; i < BDPConstants.TableCRC16Size; ++i)
        {
            ushort CRC = 0;
            ushort c = i;
            for (int j = 0; j < 8; ++j)
            {
                if (((CRC ^ c) & 0x0001) > 0)
                    CRC = (ushort)((CRC >> 1) ^ BDPConstants.Polynominal);
                else
                    CRC = (ushort)(CRC >> 1);
                c = (ushort)(c >> 1);
            }
            TableCRC16[i] = CRC;
        }
    }

    protected ushort CalcCRC16(byte[] aData)
    {
        ushort CRC = 0;
        for (int i = 0; i < aData.Length; ++i)
            CRC = (ushort)(TableCRC16[(CRC ^ aData[i]) & 0xFF] ^ (CRC >> 8));
        return CRC;
    }

在某处初始化表(例如表单构造函数):

InitCRC16Table();

然后在代码中使用它,就像这样,

您可以使用字节列表而不是数组,更方便地将字节数据打包在“数据包”中进行发送

uint CRC = CalcCRC16(byte[] aByte)
// You need to split your CRC in two bytes of course
byte CRCHW = (byte)((CRC) / 256); // that's your 0x56
byte CRCLW = (byte)(CRC);         // that's your 0x27

LOL, I've encountered exactly the same STATUS REQUEST sequense, i'm currently developing software to use with CashCode Bill Validator:). Here's the code worked for me, it's CRC16-CCITT with reversed polynomial equals 0x8408 (BDPConstants.Polynomial in the code). That's the code worked for me:

    // TableCRC16Size is 256 of course, don't forget to set in somewhere
    protected ushort[] TableCRC16 = new ushort[BDPConstants.TableCRC16Size];
    protected void InitCRC16Table()
    {
        for (ushort i = 0; i < BDPConstants.TableCRC16Size; ++i)
        {
            ushort CRC = 0;
            ushort c = i;
            for (int j = 0; j < 8; ++j)
            {
                if (((CRC ^ c) & 0x0001) > 0)
                    CRC = (ushort)((CRC >> 1) ^ BDPConstants.Polynominal);
                else
                    CRC = (ushort)(CRC >> 1);
                c = (ushort)(c >> 1);
            }
            TableCRC16[i] = CRC;
        }
    }

    protected ushort CalcCRC16(byte[] aData)
    {
        ushort CRC = 0;
        for (int i = 0; i < aData.Length; ++i)
            CRC = (ushort)(TableCRC16[(CRC ^ aData[i]) & 0xFF] ^ (CRC >> 8));
        return CRC;
    }

Initialize the table somewhere (e.g. Form constructor):

InitCRC16Table();

then use it in your code just like that,

You can use List of bytes instead of array, more convinient to pack byte data in the 'packet' for sending

uint CRC = CalcCRC16(byte[] aByte)
// You need to split your CRC in two bytes of course
byte CRCHW = (byte)((CRC) / 256); // that's your 0x56
byte CRCLW = (byte)(CRC);         // that's your 0x27
剑心龙吟 2024-10-25 07:20:08

它有效并且不需要表:

    /// <summary>
    /// Gens the CRC16.
    /// CRC-1021 = X(16)+x(12)+x(5)+1
    /// </summary>
    /// <param name="c">The c.</param>
    /// <param name="nByte">The n byte.</param>
    /// <returns>System.Byte[][].</returns>
    public ushort GenCrc16(byte[] c, int nByte)
    {
        ushort Polynominal = 0x1021;
        ushort InitValue = 0x0;

        ushort i, j, index = 0;
        ushort CRC = InitValue;
        ushort Remainder, tmp, short_c;
        for (i = 0; i < nByte; i++)
        {
            short_c = (ushort)(0x00ff & (ushort) c[index]);
            tmp = (ushort)((CRC >> 8) ^ short_c);
            Remainder = (ushort)(tmp << 8);
            for (j = 0; j < 8; j++)
            {

                if ((Remainder & 0x8000) != 0)
                {
                    Remainder = (ushort)((Remainder << 1) ^ Polynominal);
                }
                else
                {
                    Remainder = (ushort)(Remainder << 1);
                }
            }
            CRC = (ushort)((CRC << 8) ^ Remainder);
            index++;
        }
        return CRC;
    }

it works and dose not need table:

    /// <summary>
    /// Gens the CRC16.
    /// CRC-1021 = X(16)+x(12)+x(5)+1
    /// </summary>
    /// <param name="c">The c.</param>
    /// <param name="nByte">The n byte.</param>
    /// <returns>System.Byte[][].</returns>
    public ushort GenCrc16(byte[] c, int nByte)
    {
        ushort Polynominal = 0x1021;
        ushort InitValue = 0x0;

        ushort i, j, index = 0;
        ushort CRC = InitValue;
        ushort Remainder, tmp, short_c;
        for (i = 0; i < nByte; i++)
        {
            short_c = (ushort)(0x00ff & (ushort) c[index]);
            tmp = (ushort)((CRC >> 8) ^ short_c);
            Remainder = (ushort)(tmp << 8);
            for (j = 0; j < 8; j++)
            {

                if ((Remainder & 0x8000) != 0)
                {
                    Remainder = (ushort)((Remainder << 1) ^ Polynominal);
                }
                else
                {
                    Remainder = (ushort)(Remainder << 1);
                }
            }
            CRC = (ushort)((CRC << 8) ^ Remainder);
            index++;
        }
        return CRC;
    }
揽清风入怀 2024-10-25 07:20:08

您实际上使用的是 CRC-XMODEM LSB-reverse(带有 0x8408 系数)。此演算的 C# 代码为:

public void crc_bytes(int[] int_input)
{    
   int_array = int_input;
   int int_crc = 0x0; // or 0xFFFF;

   int int_lsb;
   for (int int_i = 0; int_i < int_array.Length; int_i++)
   {
      int_crc = int_crc ^ int_array[int_i];
      for (int int_j = 0; int_j < 8; int_j ++ )
      {
         int_lsb = int_crc & 0x0001; // Mask of LSB
         int_crc = int_crc >> 1;
         int_crc = int_crc & 0x7FFF;
         if (int_lsb == 1)
            int_crc = int_crc ^ 0x8408;
      }
   }

   int_crc_byte_a = int_crc & 0x00FF;
   int_crc_byte_b = (int_crc >> 8) & 0x00FF;
}

阅读更多内容(或下载项目):

http://www.cirvirlab.com/index.php/c-sharp-code-examples/141-c-sharp-crc-computation.html

You are actually using CRC-XMODEM LSB-reverse (with 0x8408 coefficient). C# code for this calculus is:

public void crc_bytes(int[] int_input)
{    
   int_array = int_input;
   int int_crc = 0x0; // or 0xFFFF;

   int int_lsb;
   for (int int_i = 0; int_i < int_array.Length; int_i++)
   {
      int_crc = int_crc ^ int_array[int_i];
      for (int int_j = 0; int_j < 8; int_j ++ )
      {
         int_lsb = int_crc & 0x0001; // Mask of LSB
         int_crc = int_crc >> 1;
         int_crc = int_crc & 0x7FFF;
         if (int_lsb == 1)
            int_crc = int_crc ^ 0x8408;
      }
   }

   int_crc_byte_a = int_crc & 0x00FF;
   int_crc_byte_b = (int_crc >> 8) & 0x00FF;
}

Read more (or download project):

http://www.cirvirlab.com/index.php/c-sharp-code-examples/141-c-sharp-crc-computation.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文