gpt4 book ai didi

modbus - CRC16 (ModBus) - 计算算法

转载 作者:行者123 更新时间:2023-12-03 21:04:38 29 4
gpt4 key购买 nike

我正在使用 ModBus RTU,并且我正在尝试弄清楚如何计算 CRC16。
我不需要代码示例。我只是对机制很好奇。
我了解到基本的 CRC 是数据字的多项式除法,根据多项式的长度,用零填充。
下面的测试示例应该检查我的基本理解是否正确:

  • 数据字:0100 1011
  • 多项式:1001 (x3+1)
  • 由于最高指数 x3
  • 填充了 3 位
  • 计算:0100 1011 000/1001 -> 余数:011

  • 计算。
    01001011000
    1001
    0000011000
    1001
    01010
    1001
    0011

    编辑 1:到目前为止,Mark Adler 在之前的评论/答案中已经验证过。

    在寻找答案时,我看到了许多不同的方法,包括反转、依赖小端或大端等,这些方法改变了给定 011 的结果。 .

    Modbus RTU CRC16

    当然,我很想了解不同版本的 CRC 是如何工作的,但我的主要兴趣是简单地了解这里应用的机制。到目前为止我知道:
  • x16+x15+x2+1 是多项式:0x18005 或 0b11000000000000101
  • 初始值为 0xFFFF
  • 十六进制消息示例:01 10 C0 03 00 01
  • 上述消息的 CRC16 十六进制:C9CD

  • 我确实像上面的例子一样手动计算了这个,但我不想在这个问题中用二进制写下来。我认为我转换成二进制是正确的。我不知道如何合并初始值——它是用来填充数据字而不是零吗?还是我需要颠倒答案?还有什么?
  • 第一次尝试:用零填充 16 位。
    计算出的二进制余数为 1111 1111 1001 1011这是 FF9B十六进制,对于 CrC16/Modbus 不正确,但对于 CRC16/Bypass 是正确的
  • 第二次尝试:由于初始值,用 1 填充 16 位。
    计算出的二进制余数为 0000 0000 0110 0100这是 0064在十六进制和不正确。

  • 如果有人能解释或澄清我的假设,那就太好了。老实说,我确实花了很多时间寻找答案,但每一个解释都是基于 C/C++ 或其他我不理解的代码示例。提前致谢。

    EDIT1:根据 this站点,“第一次尝试”指向另一个具有相同多项式但不同初始值 (0x0000) 的 CRC16 方法,这告诉我,计算应该是正确的。
    crccalc
    如何合并初始值?

    EDIT2:Mark Adlers Answer 可以解决问题。但是,现在我可以计算 CRC16/Modbus,还有一些问题需要澄清。不需要但赞赏。

    A)计算顺序是:...?
  • 第一次将 RefIn 应用于完整输入(包括填充位)
  • 第二 xor InitValue with (in CRC16) for the first 16 bits
  • 第三次应用 RefOut 以获得完整的输出/余数(CRC16 中的余数最大 16 位)

  • B) 引用 RefIn 和 RefOut:它是否总是反射(reflect)输入的 8 位和输出的所有位,但我使用 CRC8 或 CRC16 或 CRC32?

    C) 我所指的网站中的第 3(检查)和第 8(XorOut)列是什么意思?后者似乎相当容易,我猜它是通过计算值 xor 来应用的。在 RefOut 之后就像 InitValue 一样?

    最佳答案

    让我们一步一步来。您现在知道如何正确计算 CRC-16/BUYPASS,所以我们将从那里开始。

    让我们来看看 CRC-16/CCITT-FALSE。该值的初始值不为零,但仍将 RefIn 和 RefOut 设为假,如 CRC-16/BUYPASS。要计算数据的 CRC-16/CCITT-FALSE,您可以使用 0xffff 的 Init 值对数据的前 16 位进行异或运算。这给出了 fe ef C0 03 00 01 。现在做你所知道的,但使用多项式 0x11021 。您将获得表中的内容 0xb53f

    现在您知道如何应用 Init。下一步是处理 RefIn 和 RefOut 为真。我们将使用 CRC-16/ARC 作为示例。 RefIn 意味着我们反射(reflect)输入的每个字节中的位。 RefOut 意味着我们反射(reflect)了余数的位。输入消息是: 80 08 03 c0 00 80 。除以多项式 0x18005 我们得到 0xb34b 。现在我们反射(reflect)所有这些位(不是每个字节,而是所有 16 位),我们得到 0xd2cd 。这就是您在表中看到的结果。

    我们现在有了计算 CRC-16/MODBUS 所需的东西,它有一个非零的初始值 (0xffff) 和 RefIn 和 RefOut 为真。我们从消息开始,每个字节中的位被反射,前 16 位被反转。那是 7f f7 03 c0 00 80 。除以 0x18005 得到余数 0xb393 。反射(reflect)这些位,我们得到 0xc9cd ,即预期的结果。

    Init 的异或在反射后应用,您可以使用该表中的 CRC-16/RIELLO 进行验证。

    添加问题的答案:

    A) RefIn 与填充位无关。您反射(reflect)了输入字节。但是,在实际计算中,您会反射多项式,这会同时处理两次反射。

    B) 是的。

    C) 是的,XorOut 是您的独占或最终结果。校验是ASCII中九个字节“123456789”的CRC。

    关于modbus - CRC16 (ModBus) - 计算算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55179867/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com