【问题标题】:Caculating Crc for 5 bit poly (0x15)计算 5 位多边形 (0x15) 的 Crc
【发布时间】:2021-03-02 23:30:47
【问题描述】:

我有两个 CrC 需要解决。 多项式长度:8 位,隐含第 9 位 1 位 多项式值:0x85 初始值:0x00

多项式长度:5 位,隐含第 6 个 1 位 多项式值:0x15 初始值:0x00

My first was very easy, with the following code. 

  byte generator = 0x85;
            byte crc = 0; /* start with 0 so first byte can be 'xored' in */

            foreach (byte currByte in bytes)
            {
                crc ^= currByte; /* XOR-in the next input byte */

                for (int i = 0; i < 8; i++)
                {
                    if ((crc & 0x80) != 0)
                    {
                         crc = (byte)((crc << 1) ^ generator);
                    }
                    else
                    {
                        crc <<= 1;
                    }
                }
            }

            return crc;

但是对于我的生活,我不明白 5 位是如何工作的。当然生成器是 0x15 但在上面不起作用。我想也许我运行循环 5 次而不是 8 次,但也没有得到它。

多项式 0x15 的示例 CRC。 0x80, 0x00 应该得到 0x01 的 5bit crc

0x00, 0x20 应该得到 0x15 的 5bit crc

0x01,0x00 应该得到 0x16 的 5bit crc

0x01,0x20 应该得到 0x03 的 5bit crc

0x01,0x40 应该得到 0x09 的 5bit crc

0x01,0x60 应该得到 0x1c 的 5bit crc

为了更好地理解这是如何工作的。有一个 2 字节的内存地址,每 32 个字节步进。由于 5 个额外的位从未使用过,因此 crc 进入其中。

内存地址0x0020示例

0000000000100000 (0x20)

or'd crc 结果为 0x15

0000000000010101 (0x15)

=

0000000000110101 (0x35)

所以我需要获取我的地址 0x0020 并返回一个 crc 0x15。上面提到了 Crc 的详细信息。它是经过验证的 Crc,可用于给定的应用程序。

根据下面的建议,但没有得到我应该得到的结果。

byte generator = 0x15;
byte crc = 0; /* start with 0 so first byte can be 'xored' in */

foreach (byte currByte in bytes)
{
    crc ^= currByte; /* XOR-in the next input byte */

    for (int i = 0; i < 8; i++)
    {
        if ((crc & 0x80) != 0)
        {
             crc = (byte)((crc << 1) ^ (generator << 3));
        }
        else
        {
            crc <<= 1;
        }
    }
}
return (byte)(crc >>= 3);

【问题讨论】:

  • 您的第二个代码示例不完整。 generator 设置为什么?
  • 你需要添加一个你正在使用的语言的标签。
  • 是说在 OP -“当然生成器是 0x15”
  • 为了查找错误,任何来源都需要完整,而不是从文本中推断出来。还是没有。
  • 您需要提供更多示例消息和相关的 CRC。您的 CRC 描述与您的示例不匹配。

标签: c# crc


【解决方案1】:

您需要if ((crc &amp; 0x20) != 0),最后crc &amp;= 0x1f; 以消除在字节中向上移动的无关位。

您还需要对 CRC 的正确位上的数据进行异或。

这是一个 C 语言示例:

#include <stddef.h>
#include <stdint.h>

uint8_t crc5(uint8_t crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    crc <<= 3;
    for (size_t i = 0; i < len; i++) {
        crc ^= data[i];
        for (unsigned k = 0; k < 8; k++) {
            crc = crc & 0x80 ? (crc << 1) ^ 0xa8 : crc << 1;
        }
    }
    crc >>= 3;
    return crc;
}

更新:

OP 更正了用于 CRC 的数据。它是 16 位地址的前 11 位,低 5 位始终为零。然后 5 位 CRC 替换那些低 5 个零作为发送的内容。

在这种情况下,上述例程可用于检查消息,将 16 位地址 + CRC 处理为两个字节。正确消息的结果将为零。例如,01 7c 的这个 CRC 给出了0

如果这个 5 位 CRC 总是在 16 位值的高 11 位上计算,那么这个例子将计算 5 位 CRC 并检查它:

#include <stdint.h>

uint16_t crc5h(uint16_t addr, int k) {
    while (k--)
        addr = addr & 0x8000 ? (addr << 1) ^ 0xa800 : addr << 1;
    return addr >> 11;
}

当地址的低五位为零且k 等于11 时,返回要插入的五位CRC。与生成的 CRC 异或的地址是要发送的内容。如果将该 16 位消息提供给 crc5h()k 等于 16,则所有 16 位都将被处理,并且如果接收到的消息没有错误,结果将始终为零。

【讨论】:

  • 代码建议很容易,我没想过删除这些位,但在我的尝试中我只运行了 5 次循环。我想我可能误解或忘记包含一些信息,因为它总是返回 1。我在上面显示我的编辑。
  • 要处理一个字节中的八位,您需要运行循环八次。
  • 您需要将数据异或到正确的位置,将数据的最高位放在CRC的最高位上。您可以通过移动 CRC 来做到这一点。
  • 哦,抱歉,c# 目前不是我的第一语言。但是尝试将代码转换为 c# 并不是很有效,因为它存在字节和转换问题。这个例子也没有显示我的多项式。非常抱歉,非常感谢您在这里提供的帮助,但不幸的是,这让我感到困惑。
  • 哦,我看到您的示例使用 crc 作为多项式,我在上面调整了我的 c# 代码。还是没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 2013-04-19
  • 2017-01-10
相关资源
最近更新 更多