计算HDLC帧的FCS(CRC)

时间:2011-11-02 16:30:28

标签: serial-port frame checksum crc

我有以下框架:

7e  01 00  00  01  00  18  ef  00  00  00   b5   20 c1 05 10 02 71 2e 1a c2 05 10 01 71 00 6e 87 02 00 01 42 71 2e 1a 01 96 27 be 27 54 17 3d b9 93 ac 7e

如果我理解正确的话,那就是计算FCS的帧的这一部分:

010000010018ef000000b520c1051002712e1ac205100171006e8702000142712e1a019627be2754173db9

我已尝试将其输入多个在线计算器,但我无法从上述数据中生成0x93ac。

输入类型为十六进制的

http://www.lammertbies.nl/comm/info/crc-calculation.html

0x93ac是如何到达的?

谢谢,

百里

3 个答案:

答案 0 :(得分:8)

回答那些在寻找建议时来到这里的人。

关键是密切相关的ITU-T建议中的几点(例如Q.921,已在网上提供了很长时间)说:

1。首先发送(并因此接收)最低位比特

这种遗留行为与日常生活惯例相反,其中最高位数字首先按读取顺序写入,并且所有通用在线计算器和库使用常规顺序执行计算并提供可选设置以促进逆转一。 因此,您必须询问在线计算器

  • 反转您在"传统"中输入的消息中的位顺序。格式化之前执行计算,
  • 反转结果的位顺序,以便让它们进入 与消息本身相同的顺序

相当合理的是,有些计算器只为两者提供了一个共同的设置。

这就是设置"反向数据字节"和#34;在最终XOR"之前反转CRC结果在上一个答案中推荐;

2。在发送

之前,CRC计算的结果必须是位反转的

位反转是" xor by 0xffff的另一个名称......"。在将CRC计算结果作为消息FCS(消息的最后两个字节,在您的示例中为' 93 ac')发送之前,有一个目的是对CRC计算结果进行位反转。 详见第4点。

这就是设置"最终值ffff",其名称相当误导,因为它实际上定义了与计算结果相关的模式。由于几种CRC类型需要这样的操作,因此只有xor模式从0(无操作)到0xfff ...(完全反转)不等,通用计算器/库提供简化使用。

3。计算必须包括处理前导序列0xffff

这就是点"初始值ffff"。

4。在接收(检查)方面,建议通过CRC计算推送完整的消息,即包括FCS,并期望结果为0x1d0f

这背后有一些聪明的想法:

  • CRC算法的固有属性是

    CRC(x.CRC(x))

    始终为0(x表示原始邮件,"。"表示连接)。

  • 通过计算而不是运行完整的消息 仅计算消息本身并与FCS进行比较 单独接收意味着更简单的算法(甚至电路) 在接收方。

  • 然而,
  • 很容易造成编码错误导致结果变为0.幸运的是,多亏了CRC算法的内在属性,

    CRC(x。(CRC(x))')

    产生一个独立于x且不等于0的常数值(至少对于CRC-CCITT,我们在这里讨论)。 "'" sign表示第2点所要求的位反转。

答案 1 :(得分:4)

首先,CRC值为0xac93

使用此计算器:http://www.zorc.breitbandkatze.de/crc.html

  • 设置CRC顺序16
  • Polynomial 1021
  • 初始值ffff
  • 最终价值ffff
  • “reverse data bytes”
  • “在最终XOR之前反转CRC结果”
  • 输入您的序列:

    %01%00%00%01%00%18%ef%00%00%00%b5%20%c1%05%10%02%71%2e%1a%c2%05%10%01%71%00%6e%87%02%00%01%42%71%2e%1a%01%96%27%be%27%54%17%3d%b9
    
  • 按“计算”,即可获得0xAC93

答案 2 :(得分:0)

这是用于HDLC CRC计算的简单Python脚本。您可以将其用于DLMS

def byte_mirror(c):

    c = (c & 0xF0) >> 4 | (c & 0x0F) << 4
    c = (c & 0xCC) >> 2 | (c & 0x33) << 2
    c = (c & 0xAA) >> 1 | (c & 0x55) << 1

    return c

CRC_INIT=0xffff
POLYNOMIAL=0x1021
DATA_VALUE=0xA0

SNRM_request=[ 0x7E, 0xA0, 0x08, 0x03, 0x02, 0xFF, 0x93, 0xCA, 0xE4, 0x7E]

print("sent>>", end=" ")

for x in SNRM_request:
  if x>15:
       print(hex(x), end=" ")
  else:
       a=str(hex(x))
       a = a[:2] + "0" + a[2:]
       print(a, end=" ")

lenn=len(SNRM_request)
print(" ")

crc = CRC_INIT



for i in range(lenn):

    if( (i!=0) and (i!=(lenn-1)) and (i!=(lenn-2)) and (i!=(lenn-3)) ):

        print("i>>",i)

        c=SNRM_request[i]
        c=byte_mirror(c)
        c = c << 8
    
        print(hex(c))

        for j in range(8):
  
            print(hex(c))
            print("CRC",hex(crc))

            if (crc ^ c) & 0x8000:
                crc = (crc << 1) ^ POLYNOMIAL
            else:
                crc = crc << 1

            c = c << 1   
            crc=crc%65536
            c  =c%65536


print("CRC-CALC",hex(crc))

crc=0xFFFF-crc          
print("CRC- NOT",hex(crc))

crc_HI=crc//256
crc_LO=crc%256

print("CRC-HI",hex(crc_HI))
print("CRC-LO",hex(crc_LO))

crc_HI=byte_mirror(crc_HI)
crc_LO=byte_mirror(crc_LO)

print("CRC-HI-zrc",hex(crc_HI))
print("CRC-LO-zrc",hex(crc_LO))

crc=256*crc_HI+crc_LO
print("CRC-END",hex(crc))