Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating CRC16 in Python for modbus

Firstly, sorry! I am a beginner...

I got the following byte sequence on a modbus: "01 04 08 00 00 00 09 00 00 00 00 f8 0c". The CRC on bold on this byte sequence is correct. However, to check/create the CRC I have to follow the device especs that states:

The error checking must be done using a 16 bit CRC implemented as two 8 bit bytes. The CRC is appended to the frame as the last field. The low order byte of the CRC is appended first, followed by the high order byte. Thus, the CRC high order byte is the last byte to be sent in the frame. The polynomial value used to generate the CRC must be 0xA001.

Now, how can I check the CRC using crcmod? My code is:

import crcmod
crc16 = crcmod.mkCrcFun(0x1A001, rev=True, initCrc=0xFFFF, xorOut=0x0000)
print crc16("0104080000000900000000".decode("hex"))

I tried everything but I can't get the "f8 0C" that is correct on the byte sequence...

like image 291
Moacir Ferreira Avatar asked May 28 '26 12:05

Moacir Ferreira


2 Answers

A simple implementation of the MODBUS CRC without any additional lib:

def modbusCrc(msg:str) -> int:
    crc = 0xFFFF
    for n in range(len(msg)):
        crc ^= msg[n]
        for i in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

msg = bytes.fromhex("0104080000000900000000")
crc = modbusCrc(msg)
print("0x%04X"%(crc))            

ba = crc.to_bytes(2, byteorder='little')
print("%02X %02X"%(ba[0], ba[1]))

The output is:

0x0CF8
F8 0C
like image 83
rams Avatar answered May 31 '26 18:05

rams


Use 0x18005 instead of 0x1A001.

like image 22
Mark Adler Avatar answered May 31 '26 18:05

Mark Adler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!