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

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

闾丘京
2023-03-14

我目前正在建立步进电机控制器和计算机之间的通信,用C#编写一个应用程序(这是我第一次使用这种编程语言,虽然我不是计算机科学家,而是工业工程师,但我肯定有一些优化功能的方法,我不知道,关于这一点的任何建议也将非常感谢)。因此,我一直使用控制器必须与其通信的RS-485,并实现了一个生成所需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}。

共有1个答案

闽经纬
2023-03-14

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

我在这个链接中找到了应该正确生成CRC的代码。它遵循您共享链接到的文档第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;  
}
 类似资料:
  • 因此,我的问题是:如何从整数结果到所需的双十六进制结果?我试了几个选择,都没有成功。 注意:我使用的是Qt,所以如果有人能找到实现QByteArray或其他Qt友好代码的解决方案,我会很高兴的。无论哪种方式,不使用Qt、C或C++的解决方案都是无用的:P

  • 我能够重新创建包罚款,除了2字节“5C B1”。根据文档,5C b1字节是数据包上的crc-ccit16,在crc-16时隙中有0。CRC16函数返回5c字节,但不返回b1字节。 我使用下面的代码来计算CRC:

  • 我有一个通过RS232 COM与计算机通信的终端。我得到的协议说,我必须发送一定的字节组合和CRC 16 IBM计算的数据在最后发送 我还得到了一个C编写的应用程序,我可以用它来测试,该应用程序编写了一个带有发送数据和接收数据的日志。在该日志中,我查看是否向终端发送了以下字符串。我还必须发送数据06 35的这个CRC16 IBM结果。 我已经设法以某种方式将作为示例给出的C方法翻译成C#。但我的结

  • 在C语言中也有一个类似的问题被问到和回答,但我在C#中遇到了一些困难。 我有48位数据,现在我需要生成16位CRC,下面是代码: 但是上面的代码,给了我错误的输出,请建议我如果有什么更好的方法做它。

  • 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

  • 编辑:底部的工作代码 我对编程相对较新,我正在试图理解为什么这不起作用。我决定通过一个函数而不是来处理卡片,以保持它尽可能模块化。这是我下面的代码;我知道错误与指针有关,但我不明白我做错了什么。 工作代码: