如何产生从C#的CRC-16 [英] How to generate a CRC-16 from C#

查看:475
本文介绍了如何产生从C#的CRC-16的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想生成使用CRC-16 C#。我使用RS232的硬件需要输入字符串是十六进制。下面的截图显示正确的转换,对于一个测试,我需要8000是0xC061,但其产生的CRC-16必须能够在任何给定的十六进制字符串转换成C#方法。





我使用Nito.KitchenSink.CRC试图



我也曾尝试下面生成8009当8000输入 -

 公共字符串CalcCRC16(字符串strInput)
{
USHORT CRC = 0×0000;
字节[]数据= GetBytesFromHexString(strInput);
的for(int i = 0; I< data.Length;我++)
{
CRC ^ =(USHORT)(数据[1] - ;< 8);
为(INT J = 0; J< 8; J ++)
{
如果((CRC&安培;为0x8000)0)
CRC =(USHORT)(( CRC&所述;&。1)^ 0x8005);
,否则
&CRC LT;< = 1;
}
}
返回crc.ToString(X4);
}

公共字节[] GetBytesFromHexString(字符串strInput)
{
字节[] = bytArOutput新的字节[] {};
如果(string.IsNullOrEmpty(strInput)及!&安培; strInput.Length%2 == 0)
{
SoapHexBinary hexBinary的= NULL;

{
hexBinary的= SoapHexBinary.Parse(strInput);
如果(hexBinary的!= NULL)
{
bytArOutput = hexBinary.Value;
}
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}
返回bytArOutput;
}


解决方案

下面我们走;注意,这是CRC-16的的具体的味道的 - 这是令人困惑地说只是CRC-16。这种借用 http://www.sanity-free.com/ 一些实现细节 - 注意我有使得静态,而不是基于实例的

 使用系统。 

静态类节目
{
静态无效的主要()
{
列输入=8000;
VAR字节= HexToBytes(输入);
字符串十六进制= Crc16.ComputeChecksum(字节)的ToString(X2);
Console.WriteLine(十六进制); // C061
}
静态的byte [] HexToBytes(字符串输入)
{
的byte []结果=新的字节[input.Length / 2];
的for(int i = 0; I< result.Length;我++)
{
结果[I] = Convert.ToByte(input.Substring(2 * 1,2),16 );
}
返回结果;
}

公共静态类CRC16
{
常量USHORT多项式= 0xA001异或;
静态只读USHORT [] =表USHORT新[256];

公共静态USHORT ComputeChecksum(字节[]字节)
{
USHORT CRC = 0;
的for(int i = 0; I< bytes.Length ++ I)
{
字节指数=(字节)(CRC ^字节[I]);
CRC =(USHORT)((CRC>> 8)^表[指数]);
}
返回CRC;
}

静态CRC16()
{
USHORT值;
USHORT温度;
为(USHORT我= 0; I< table.Length ++ I)
{
值= 0;
TEMP = I;
表示(字节J = 0; J&下; 8; ++ j)条
{
如果(((值^温度)及!×0001)= 0)
{
值=(USHORT)((值GT;→1)^多项式);
}
,否则
{
值>> = 1;
}
&温度GT;> = 1;
}
表[i] =价值;
}
}
}
}


I am trying to generate a CRC-16 using C#. The hardware I am using for RS232 requires the input string to be HEX. The screenshot below shows the correct conversion, For a test, I need 8000 to be 0xC061, however the C# method that generates CRC-16 must be able to convert any given HEX string.

I have tried using Nito.KitchenSink.CRC

I have also tried the below which generates 8009 when 8000 is inputted -

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

解决方案

Here we go; note that this is a specific flavor of CRC-16 - it is confusing to say just "CRC-16". This borrows some implementation specifics from http://www.sanity-free.com/ - note I have made it static rather than instance-based.

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

这篇关于如何产生从C#的CRC-16的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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