0

我有一个从串行端口读取 7E0302403F387E 的传入数据包。

开始和结束标志为 7E,FCS/CRC 为 3F38,数据为 030240。FCS 是根据 RFC 1662 中指定的算法计算的。https: //www.rfc-editor.org/rfc/rfc1662#appendix-A

这是我用来为 030240 生成 FCS 的代码:

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 = 0x8408;
        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;
            }
        }
    }

这就是我所说的:

//string input = "00 03 00 02 04 00";
string input = "030240";
var bytes = HexToBytes(input);
string hexe = Crc16.ComputeChecksum(bytes).ToString("x2");

我应该得到 3F38 的 FCS,但我得到的是 9ED0。我究竟做错了什么?

编辑1:

我正在~\0\u0003\0\u0002\u0004\0?8~从串行端口读取。我可以将其转换为7E-03-02-40-3F-38-7Eor 或7e-5c-30-5c-75-30-30-30-33-5c-30-5c-75-30-30-30-32-5c-75-30-30-30-34-5c-30-3f-38-7e. 第一个太短,第二个太长。我应该得到 10 个字节。有小费吗?

编辑2:

我正在使用 ASCII_To_Hex 转换~\0\u0003\0\u0002\u0004\0?8~7E-03-02-40-3F-38-7E

public string ASCII_To_Hex(string ASCII)
    {
        char[] charValues = dataIN.ToCharArray();
        string hexOutput = "";
        foreach (char _eachChar in charValues)
        {
            // Get the integral value of the character.
            int value = Convert.ToInt32(_eachChar);
            // Convert the decimal value to a hexadecimal value in string form.
            hexOutput += String.Format("{0:X}", value);
            // to make output as your eg 
            //  hexOutput +=" "+ String.Format("{0:X}", value);

        }
        return hexOutput;
    }

我可以在此处进行哪些更改以正确破译传入的数据包?

编辑3:

根据 Mark 的建议,我做了以下更改:

public static class Crc16
    {
        const ushort polynomial = 0x1021;

        static readonly ushort[] table = new ushort[256];

        public static ushort ComputeChecksum(byte[] bytes)
        {
            ushort crc = 0xffff;
            for (int i = 0; i < bytes.Length; ++i)
            {
                byte index = (byte)(crc ^ bytes[i]);
                crc = (ushort)((crc >> 8) ^ table[index]);
            }
            return (ushort)~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;
            }
        }
    }

这就是我所说的:

string hex = "00-03-00-02-04-00";
        hex = hex.Replace("-", "");
        var bytes = HexToBytes(hex);
        string hexe = Crc16.ComputeChecksum(bytes).ToString("X2");

我得到FO93而不是389B

4

1 回答 1

2

根据所链接的附录,CRC 的初始值为0xffff,而不是 0,您需要将结果与 进行异或,0xffff以获得 FCS 放入数据包。

但是,这仍然不适用于您的示例数据包。我只能猜测您的示例数据包未正确提取或识别。

更新:

从下面的 OP 评论和一些推论来看,消息中的实际数据是"~\x00\x03\x00\x02\x04\x00\x9b\x38~". OP 出于某种原因遗漏了三个零字节,并且 OP 以一种将一个字节作为问号隐藏的方式打印了它。

现在CRC 计算正确0x389b,存储在消息 little-endian 中0x9b 0x38。为此,您必须将我上面的评论应用于初始值和最终异或。

于 2021-03-05T02:33:11.907 回答