CRC-16/Modbus C# 中的实现出现故障

CRC-16/Modbus Implementation in C# malfunction

我目前正在设置步进电机控制器和计算机之间的通信,用 C# 编写应用程序(这是我第一次使用这种编程语言,虽然我不是计算机科学家但是一位工业工程师,为什么我确定有一些我不知道的优化功能的方法,关于这件事的任何建议也将非常感激)。因此,我一直在使用控制器必须与之通信的 RS-485,并且我已经实现了一种生成所需的 CRC(循环冗余校验)字节的算法。

我的问题就是从这里开始的。我找不到我的函数没有生成正确 CRC 值的原因。我检查了一些 CRC 的在线计算器,我还使用了 Modbus Guide 中出现的示例(其中还解释了代码是如何实现的)。

这是我为 CRC 的微积分编写的代码:

class Program
    {
        static void Main(string[] args)
        {
            // 0x05, 0x06, 0x17, 0x70, 0x00, 0x01 
            byte[] prueba = new byte[] { 0x02, 0x07 };
            byte[] result = Aux.CRC(prueba);
            Console.WriteLine(result[0] + " " + result[1]);
        }
    }

class Aux{
public static byte[] CRC(byte[] to_evaluate)
        {
            byte[] CRC_Byte = new byte[2] { 0, 0 };
            UInt16 CRC_Register = 0xFFFF;            //16 bits 1111.1111.1111.1111
            UInt16 CRC_pol = 0xa001;                 //16 bits 1010.0000.0000.0001

            foreach (UInt16 byte_val in to_evaluate)
            {
                CRC_Register ^= byte_val;
                Console.WriteLine("XOR inicial : {0:X}", CRC_Register);

                for (byte i = 0; i < 8; i++)
                {
                    CRC_Register >>= 1;
                    Console.WriteLine("Desplazamiento " + (i + 1) + ": {0:X}", CRC_Register);

                    if ((CRC_Register & 1) != 0)
                    {
                        CRC_Register ^= CRC_pol;
                        Console.WriteLine("XOR: {0:X}", CRC_Register);
                    }
                }
            }
            Console.WriteLine("{0:X}",CRC_Register);

            byte low_byte_CRC = (byte)((CRC_Register << 8) >> 8);
            byte high_byte_CRC = (byte)(CRC_Register >> 8);

            CRC_Byte[0] = low_byte_CRC;
            CRC_Byte[1] = high_byte_CRC;

            return CRC_Byte;
        }
}

使用附加的测试数组和多项式 0xa001 的预期结果对于 CRC_Register 是 0x1241,对于 CRC_Byte 是 {0x41,0x12}。

我不得不在 C# 中为 PPP 实现一次 CRC 检查,这完全没有乐趣!

我在 this link 中找到了应该正确生成 CRC 的代码。它遵循您共享 link 的文档第 39 页第 6.2.2 节中的 CRC 生成过程。

// Compute the MODBUS RTU CRC
UInt16 ModRTU_CRC(byte[] buf, int len)
{
    UInt16 crc = 0xFFFF;
  
    for (int pos = 0; pos < len; pos++) 
    {
        crc ^= (UInt16)buf[pos];          // XOR byte into least sig. byte of crc
  
        for (int i = 8; i != 0; i--)      // Loop over each bit
        {    
            if ((crc & 0x0001) != 0)        // If the LSB is set
            {      
                crc >>= 1;                    // Shift right and XOR 0xA001
                crc ^= 0xA001;
            }
            else                            // Else LSB is not set
            {                            
                crc >>= 1;                    // Just shift right
            }
        }
    }
    // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
    return crc;  
}