如何从C#生成CRC-16

时间:2014-04-04 10:33:53

标签: c# crc crc16

我正在尝试使用C#生成CRC-16。我用于RS232的硬件要求输入字符串为HEX。下面的屏幕截图显示了正确的转换。对于测试,我需要8000为0xC061,但生成CRC-16的C#方法必须能够转换任何给定的HEX字符串。

Screenshot of required output.

我尝试过使用Nito.KitchenSink.CRC

我还尝试了以下,当输入8000时生成8009 -

public string CalcCRC16(string strInput)
    {
        ushort crc = 0x0000;
        byte[] data = GetBytesFromHexString(strInput);
        for (int i = 0; i < data.Length; i++)
        {
            crc ^= (ushort)(data[i] << 8);
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 0x8000) > 0)
                    crc = (ushort)((crc << 1) ^ 0x8005);
                else
                    crc <<= 1;
            }
        }
        return crc.ToString("X4");
    }

    public Byte[] GetBytesFromHexString(string strInput)
    {
        Byte[] bytArOutput = new Byte[] { };
        if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0)
        {
            SoapHexBinary hexBinary = null;
            try
            {
                hexBinary = SoapHexBinary.Parse(strInput);
                if (hexBinary != null)
                {
                    bytArOutput = hexBinary.Value;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        return bytArOutput;
    }

2 个答案:

答案 0 :(得分:34)

我们走了;请注意,这是CRC-16的特定风味 - 仅仅说&#34; CRC-16&#34;是令人困惑的。这借鉴了http://www.sanity-free.com/的一些实现细节 - 请注意我已将其设为static而不是基于实例。

using System;

static class Program
{
    static void Main()
    {
        string input = "8000";
        var bytes = HexToBytes(input);
        string hex = Crc16.ComputeChecksum(bytes).ToString("x2");
        Console.WriteLine(hex); //c061
    }
    static byte[] HexToBytes(string input)
    {
        byte[] result = new byte[input.Length / 2];
        for(int i = 0; i < result.Length; i++)
        {
            result[i] = Convert.ToByte(input.Substring(2 * i, 2), 16);
        }
        return result;
    }

    public static class Crc16
    {
        const ushort polynomial = 0xA001;
        static readonly ushort[] table = new ushort[256];

        public static ushort ComputeChecksum(byte[] bytes)
        {
            ushort crc = 0;
            for (int i = 0; i < bytes.Length; ++i)
            {
                byte index = (byte)(crc ^ bytes[i]);
                crc = (ushort)((crc >> 8) ^ table[index]);
            }
            return crc;
        }

        static Crc16()
        {
            ushort value;
            ushort temp;
            for (ushort i = 0; i < table.Length; ++i)
            {
                value = 0;
                temp = i;
                for (byte j = 0; j < 8; ++j)
                {
                    if (((value ^ temp) & 0x0001) != 0)
                    {
                        value = (ushort)((value >> 1) ^ polynomial);
                    }
                    else
                    {
                        value >>= 1;
                    }
                    temp >>= 1;
                }
                table[i] = value;
            }
        }
    }
}

答案 1 :(得分:8)

另外,如果你想要CRC16-CCITT。

  private ushort Crc16Ccitt(byte[] bytes)
            {
                const ushort poly = 4129;
                ushort[] table = new ushort[256];
                ushort initialValue = 0xffff;
                ushort temp, a;
                ushort crc = initialValue;
                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;
                }
                for (int i = 0; i < bytes.Length; ++i)
                {
                    crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
                }
                return crc;
            }