为什么这个CRC不是一个2字节的字符串?

2024-06-14 20:42:51 发布

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

使用这个字符串“000016037000”和这个CRC16函数,结果不是一个2字节的字符串,为什么?在

def _crc16(data, bits=8):
    """private method: for calculating the CRC
    based on the standard EN50463-4

    Arguments:
        Input: data in ASCII encoding !
        Output: CRC of the data
    """
    crc = 0xFFFF
    for l in list(data):
        """or exclusive
        bin: gives the binary representation
        int: cast the string to an int with the base2
        ord: gives the ASCII code for the caracter between (0..255)
        """
        crc = crc ^ int(bin(ord(l)), 2)
        for bit in range(0, bits):
            if (crc & 0x0001) == 0x0001:
                crc = ((crc >> 1) ^ 0xA001)
            else:
                crc = crc >> 1

    return _typecasting(crc)


def _typecasting(crc):
    """gives the msb and lsb"""
    msb = hex(crc >> 8)
    lsb = hex(crc & 0x00FF)

    return lsb + msb

data = "000016037000"

print _crc16(data)

这是结果:0x00xfc,当您剥离“0x”时是0fc!CRC16应该生成2个字节的校验和,lsb为0是否正常?在


Tags: the字符串infordata字节defbits
3条回答

你似乎有很多不必要的转换,问题是关于其中一个效果。我会按执行顺序来解释。在

for l in list(data):

在这里,您将一个字符串转换成一个字母列表,每个字母本身就是一个字符串(Python不使用char数据类型)。这样做的原因是,您可以对字符串本身进行迭代;只需删除list()调用。在

^{pr2}$

作为补充说明,ord()实际上为我们提供了序数;它不一定是ASCII(事实上,没有代码>;127是ASCII格式的)。一旦我们有了这个数字,你就把它转换成二进制和反向的文本表示;如果成对的话,这两种转换都是多余的。在

msb = hex(crc >> 8)
lsb = hex(crc & 0x00FF)
return lsb + msb

对hex()的每次调用都转换为十六进制表示。与bin()一样,这是Python数字文本的形式,因此每个前缀都是0x。将它们串联起来会产生一种有点奇怪的格式(尽管仍然可以恢复,但它与任何常见格式不同)。在这一点上,最好知道你的目标是什么。在

一种猜测是,您需要一个4位十六进制格式的小尾数16位无符号整数(面向字节的十六进制转储)。我们可以使用Python的标准库来表示:

import binascii, struct
le16hex = binascii.b2a_hex(struct.pack('<H', crc))

这里<标记little endian,H标记一个无符号16位值,b2a峎hex从二进制转换为十六进制。如果我们只需要一个4位数的十六进制值(顺便匹配bigendian形式),我们可以使用"%04x"%crc。在

但是,您也会问为什么结果不是两个字节的字符串。那是因为你用十六进制要求的;结构包上面的结果正好是一个两字节的字符串。结合您输入的偶数位数,我想知道您是要处理二进制数据(如ord和struct所做的)还是全部十六进制(甚至八进制)。要理解这一点还需要更多的背景知识。在

至于最低有效字节是0,这是这个特定字符串的一个效果;它只显示一个数字是因为hex()不会产生超出需要的值。%格式化操作可以产生特定的位数。在

是的,这很正常。就像0中的0。顺便说一句,你的主循环有点太冗长了,那么:

crc = 0xFFFF
for l in data:
    crc ^= ord(l)
    for bit in range(0, bits):
        if crc & 1:
            crc = (crc >> 1) ^ 0xA001
        else:
            crc >>= 1

似乎交换lsb和msb的typecasting函数可以更简洁地编写为

^{pr2}$

注意,为了避免麻烦,这两个函数都应该只处理整数,不需要hex或{}。在

hex()函数返回前面带有0x的字符串。因此,在您的typecasting函数中,您有:

lsb = "0x00"
msb = "0xfc"

当你连接它们时,你在前面和中间都得到^ {CD2}}。在连接之前,应该从msb中删除0x

^{pr2}$

然后您将得到0x00fc

相关问题 更多 >