微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算 5 位 poly (0x15)

如何解决计算 5 位 poly (0x15)

我有两个 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);

解决方法

您需要 if ((crc & 0x20) != 0),并在最后 crc &= 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 替换发送的那些低五个零。

在这种情况下,通过将 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 位都将被处理,并且结果将始终为零,前提是该消息被正确接收。>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。