从C#端口Modbus RTU CRC到python

时间:2016-08-23 12:58:18

标签: c# python crc modbus

我正在尝试将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#-example提供的那样。

当我逐步调试两个示例时,变量'crc'在这些代码行之后具有差值:

crc ^= (UInt16)data[pos];

VS

crc ^= pos

我错过了什么?

/ Mc_Topaz

1 个答案:

答案 0 :(得分:1)

您的内部循环使用数据数组的大小而不是固定的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))