开发者

C# CRC implementation

开发者 https://www.devze.com 2023-02-12 19:24 出处:网络
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 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 ma开发者_Python百科naging 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:

C# CRC implementation


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 }


Have you tried Googling for an example? There are many of them.

Example 1: http://tomkaminski.com/crc32-hashalgorithm-c-net
Example 2: http://www.sanity-free.com/12/crc32_implementation_in_csharp.html

You also have native MD5 support in .Net through System.Security.Cryptography.MD5CryptoServiceProvider.

EDIT:

If you are looking for an 8-bit algorithm: http://www.codeproject.com/KB/cs/csRedundancyChckAlgorithm.aspx
And 16-bit: http://www.sanity-free.com/133/crc_16_ccitt_in_csharp.html


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


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消