将Modbus RTU CRC从c#移植到python

本文关键字:python Modbus RTU CRC | 更新日期: 2023-09-27 18:03:31

我正在尝试将Modbus RTU的CRC计算函数从c#移植到Python。

c#

private static ushort CRC(byte[] data)
{
    ushort crc = 0xFFFF;
    for (int pos = 0; pos < data.Length; pos++)
    {
        crc ^= (UInt16)data[pos];
        for (int i = 8; i != 0; i--)
        {
           if ((crc & 0x0001) != 0)
           {
               crc >>= 1;
               crc ^= 0xA001;
           }
           else
           {
               crc >>= 1;
           }
       }
    }
    return crc;
}

我像这样运行:

byte[] array = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x01 };
ushort u = CRC(array);
Console.WriteLine(u.ToString("X4"));
Python

def CalculateCRC(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(len(data)-1, -1, -1):
            if ((crc & 0x0001) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

我像这样运行:

data = bytearray.fromhex("010300010001")
crc = CalculateCRC(data)
print("%04X"%(crc))
  • c#示例的结果是:0xCAD5.
  • Python示例的结果是:0x8682.

我从其他应用程序的事实中知道CRC应该是0xCAD5,正如c#示例所提供的。

当我一步一步地调试两个示例时,变量'crc'在这些代码行之后具有不同的值:

crc ^= (UInt16)data[pos];

crc ^= pos

我错过了什么?

/Mc_Topaz

将Modbus RTU CRC从c#移植到python

内部循环使用数据数组的大小,而不是固定的8次迭代。试试这个:

def calc_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos 
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc
data = bytearray.fromhex("010300010001")
crc = calc_crc(data)
print("%04X"%(crc))