当前位置: 首页 > 知识库问答 >
问题:

CRC-16计算C#

朱硕
2023-03-14

我有一个通过RS232 COM与计算机通信的终端。我得到的协议说,我必须发送一定的字节组合和CRC 16 IBM计算的数据在最后发送

我还得到了一个C编写的应用程序,我可以用它来测试,该应用程序编写了一个带有发送数据和接收数据的日志。在该日志中,我查看是否向终端发送了以下字符串hexstring=“02 0004 a0 0001 01 03”。我还必须发送数据06 35的这个CRC16 IBM结果。

我已经设法以某种方式将作为示例给出的C方法翻译成C#。但我的结果与我知道我必须得到的相去甚远。

public enum Crc16Mode : ushort
    {
        ARINC_NORMAL = 0XA02B, ARINC_REVERSED = 0xD405, ARINC_REVERSED_RECIPROCAL = 0XD015,
        CCITT_NORMAL = 0X1021, CCITT_REVERSED = 0X8408, CCITT_REVERSED_RECIPROCAL = 0X8810,
        CDMA2000_NORMAL = 0XC867, CDMA2000_REVERSED = 0XE613, CDMA2000_REVERSED_RECIPROCAL = 0XE433,
        DECT_NORMAL = 0X0589, DECT_REVERSED = 0X91A0, DECT_REVERSED_RECIPROCAL = 0X82C4,
        T10_DIF_NORMAL = 0X8BB7, T10_DIF_REVERSED = 0XEDD1, T10_DIF_REVERSED_RECIPROCAL = 0XC5DB,
        DNP_NORMAL = 0X3D65, DNP_REVERSED = 0XA6BC, DNP_REVERSED_RECIPROCAL = 0X9EB2,
        IBM_NORMAL = 0X8005, IBM_REVERSED = 0XA001, IBM_REVERSED_RECIPROCAL = 0XC002,
        OPENSAFETY_A_NORMAL = 0X5935, OPENSAFETY_A_REVERSED = 0XAC9A, OPENSAFETY_A_REVERSED_RECIPROCAL = 0XAC9A,
        OPENSAFETY_B_NORMAL = 0X755B, OPENSAFETY_B_REVERSED = 0XDDAE, OPENSAFETY_B_REVERSED_RECIPROCAL = 0XBAAD,
        PROFIBUS_NORMAL = 0X1DCF, PROFIBUS_REVERSED = 0XF3B8, PROFIBUS_REVERSED_RECIPROCAL = 0X8EE7

    }

public class Crc16
{
    readonly ushort[] table = new ushort[256];

    public ushort ComputeChecksum(params 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;
    }

    public byte[] ComputeChecksumBytes(params byte[] bytes)
    {
        ushort crc = ComputeChecksum(bytes);
        return BitConverter.GetBytes(crc);
    }

    public Crc16(Crc16Mode mode)
    {
        ushort polynomial = (ushort)mode;
        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;
        }
    }
}

方法来处理接收的字节:

public ushort CalculateCRC(byte[] data)
    {
        Crc16 crcCalc = new Crc16(Crc16Mode.IBM_NORMAL);
        ushort crc = crcCalc.ComputeChecksum(data);
        return crc;
    }

在此方法中,您可以从枚举中选择多项式。

程序类中的主要内容:

            string hexString = "02 00 04 a0 00 01 01 03";
            byte[] bytes = m.HexStringToByteArray(hexString);


            ushort crc = m.CalculateCRC(bytes);

            string hexResult;
            int myInt = crc;
            hexResult = myInt.ToString("X");


            //Console.WriteLine(crc.ToString());
            Console.WriteLine(hexResult);
            Console.ReadLine();
        }
        catch (Exception ex)
        {
            Metode m = new Metode();
            m.writeError(ex.Message);
        }
    }
public byte[] HexStringToByteArray(string hexString)
    {
        hexString = hexString.Replace(" ", "");

        return Enumerable.Range(0, hexString.Length)
                 .Where(x => x % 2 == 0)
                 .Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
                 .ToArray();
    }
public string ByteArrayToHexString(byte[] byteArray)
    {
        return BitConverter.ToString(byteArray);
    }

因此hexString实际上应该是“a0000001”,即没有stx/lengtg/etx的数据。

下面是这个特殊的CRC16演算的C#代码:

public ushort CalculateCRC(byte[] data, int len)
        {
            int crc = 0, i = 0;
            while (len-- != 0)
            {
                crc ^= data[i++] << 8;
                for (int k = 0; k < 8; k++)
                    crc = ((crc & 0x8000) != 0) ? (crc << 1) ^ 0x8005 : (crc << 1);
            }
            return (ushort)(crc & 0xffff);
        }

共有1个答案

柴英锐
2023-03-14

您需要提供更多关于您试图实现的规范的信息。然而,我马上就能看出你用错了多项式。CRC例程正在右移,这意味着多项式应该是位反转的。因此,ibm_normal不能正确。

虽然ibm_reversist是一个合适的右移多项式,但它可能是也可能不是满足规范所需的多项式。此外,还可以有异或进入或离开CRC例程,这是必要的。

更新:

#include <stddef.h>
typedef unsigned char byte;
typedef unsigned short ushort;

ushort crc16ecr(byte data[], int len) {
    ushort crc = 0;
    for (int i = 0; i < len; i++) {
        crc ^= (ushort)(data[i]) << 8;
        for (int k = 0; k < 8; k++)
            crc = crc & 0x8000 ? (crc << 1) ^ 0x8005 : crc << 1;
    }
    return crc;
}
 类似资料:
  • 因此,我的问题是:如何从整数结果到所需的双十六进制结果?我试了几个选择,都没有成功。 注意:我使用的是Qt,所以如果有人能找到实现QByteArray或其他Qt友好代码的解决方案,我会很高兴的。无论哪种方式,不使用Qt、C或C++的解决方案都是无用的:P

  • FF-源地址 53-数据 70-数据

  • http://www.lammertbies.nl/comm/info/crc-calculation.html http://www.codeproject.com/articles/19059/c-ccitt-crc-algorithm 在上面与字节数组{0xee,0x01,0x13,0x00,0x06,0x1c,0x00,0x20,0x1d,0x00,0x00}的链接中,它使用CRC8(po

  • 我试图通过串行通信协议与设备通信,但在查找消息的最后2个字节使用的校验和/CRC算法时遇到了一些困难。我在各种在线crc实用程序中尝试了几种CRC16算法,比如:http://www.sunshine2k.de/coding/javascript/crc/crc_js.html http://www.zorc.breitbandkatze.de/crc.html 我也尝试了逆向工程,在REVENG

  • 我需要帮助试图验证CRC-16值(也需要帮助与CRC-32值)。我试图坐下来了解CRC是如何工作的,但我一片空白。 更多信息如下: --编辑-- 我已经包括了更多的信息。我引用的文档是TIA-102.BAAA-A(来自TIA标准)。以下是文档陈述的内容(试图尽可能避免侵犯版权): FM(x)的系数被放置在CRC字段中,其中CRC的第0个八位元组的MSB对应于x^31,而CRC的第3个八位元组的LS

  • 我正试图从一个旧的串行设备反向工程通信协议。我已经搞清楚了大部分,但仍然停留在使用的CRC算法上。我有一个主机软件,我可以生成请求消息,所以我已经包括了一个由主机软件发送的相对较短的消息转储。 下面还有一些我还没有完全解码的数据字符串,前3个字符是从属地址(类似于modbus设备地址方案),接下来的2个字符是函数代码。“10”是一个数据缓冲区请求,我还没有解码。有趣的是,在这个特定的请求中有非数字