如何使用Python计算这个CRC?

2024-10-01 13:26:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要使用Python计算这个CRC,以便与Aurora(ABB)太阳能逆变器通信。在

这是文档:http://www.drhack.it/images/PDF/AuroraCommunicationProtocol_4_2.pdf 在最后一页有计算CRC的指令,我需要用python来做。在

我得到的信息是

MESSAGE_GRID_VOLTAGE = bytes.fromhex("023b010000000000")

结果应该是:

循环电流=FF

CRC_H=2C

然后我需要发送完整的CRC信息,如下所示:

^{pr2}$

我如何在python中做到这一点呢?谢谢!在

下面是我尝试的代码:

message = "023b010000000000"

BccLo= int ("FF",16)
BccHi= int("FF", 16)

New = int(message, 16)

New = New ^ BccLo
Tmp=New << 4
New=Tmp ^ New
Tmp=New >> 5
BccLo=BccHi
BccHi= New ^ Tmp
Tmp=New << 3
BccLo=BccLo ^ Tmp
Tmp=New >> 4
BccLo=BccLo ^ Tmp

CRC_L = ~BccLo
CRC_H = ~BccHi

Tags: 文档信息httpmessagenewwwwtmpint
2条回答

根据引用文件,该算法实际上是一个标准的16位CCITT CRC。这可以用Python的标准crcmod来计算。在

给你:

import crcmod

# this is a standard CCITT CRC even if it does not look like
# (crcmod applies xorOut to initCrc, so initCrc is in reality 0xffff, not 0)
_CRC_FUNC = crcmod.mkCrcFun(0x11021, initCrc=0, xorOut=0xffff)

data = bytearray.fromhex("023b010000000000")
crc = _CRC_FUNC(data)
data.append(crc & 0xff)
data.append(((crc >> 8) & 0xff))

print (data.hex())

输出: 023B01000000FF2C

您需要将该算法应用于消息的每个字节。一个稍微复杂的问题是,Aurora PDF文件中给出的算法假设计算是用8位无符号算法执行的。为了在Python中处理这个问题,我们可以使用0xff的位掩码。下面是该代码的一个稍微优化的版本。在

def crc_16(msg):
    lo = hi = 0xff
    mask = 0xff
    for new in msg:
        new ^= lo
        new ^= (new << 4) & mask
        tmp = new >> 5
        lo = hi
        hi = new ^ tmp
        lo ^= (new << 3) & mask
        lo ^= new >> 4
    lo ^= mask
    hi ^= mask
    return hi << 8 | lo

# Test

msg = bytes.fromhex("023b010000000000")
out = crc_16(msg)
hi, lo = out >> 8, out & 0xff
print('{:04x} = {:02x} {:02x}'.format(out, hi, lo))

输出

^{pr2}$

上面的代码可以工作,但是有更简单的方法来计算crc。如果你需要计算大量的CRC,我们可以用一个表格来加速这个过程。在

正如Wikipedia Cyclic redundancy check文章所提到的,CRC算法通常是用一个十六进制数编码的多项式来指定的。这是一个函数,它使用反向多项式表示。在

def crc_16_CCITT(msg):
    poly = 0x8408
    crc = 0xffff
    for byte in msg:
        for _ in range(8):
            if (byte ^ crc) & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc >>= 1
            byte >>= 1
    return crc ^ 0xffff

为了加快速度,我们可以计算一个表。在

def make_crc_table():
    poly = 0x8408
    table = []
    for byte in range(256):
        crc = 0
        for bit in range(8):
            if (byte ^ crc) & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc >>= 1
            byte >>= 1
        table.append(crc)
    return table

table = make_crc_table()

def crc_16_fast(msg):
    crc = 0xffff
    for byte in msg:
        crc = table[(byte ^ crc) & 0xff] ^ (crc >> 8)
    return crc ^ 0xffff

# Test

msg = bytes.fromhex("023b010000000000")
out = crc_16_fast(msg)
hi, lo = out >> 8, out & 0xff
print('{:04x} = {:02x} {:02x}'.format(out, hi, lo))

如果愿意,可以打印表并将其粘贴到脚本中,这样就不必每次运行脚本时都计算表。在

相关问题 更多 >