Mc_Topaz - 1 year ago 341
C# Question

# Port Modbus RTU CRC to python from C#

I'm trying to port the CRC calculation function for Modbus RTU from C# to 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;
}
``````

Which I run like this:

``````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
``````

Which I run like this:

``````data = bytearray.fromhex("010300010001")
crc = CalculateCRC(data)
print("%04X"%(crc))
``````

• The result from the C# example is: 0xCAD5.

• The result from the Python example is: 0x8682.

I know from fact by other applications that the CRC should be 0xCAD5, as the C#-example provides.

When I debug both examples step-by-step, the variable 'crc' has difference values after these code lines:

``````crc ^= (UInt16)data[pos];
``````

VS

``````crc ^= pos
``````

What am I missing?

/Mc_Topaz

Your inner loop uses the size of the data array instead of a fixed 8 iterations. Try this:

``````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))
``````