我有两个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次,但这也没有得到它。
示例crc的多项式为0x15。0x80, 0x00应该得到0x01
的5bit CRC0x00, 0x20应该得到0x15的5bit CRC
0x01,0x00应该得到0x16的5bit CRC
0x01,0x20应该得到0x03的5bit CRC
0x01,0x40应该得到0x09
的5bit CRC0x01,0x60应该得到0x1c的5bit CRC
以便更好地理解这是如何工作的。有一个2字节的内存地址,每32字节步进一次。因为这5个额外的比特从来没有被使用过,所以crc就进入了它们。
内存地址0x0020示例
0000000000100000 (0 x20)
0x15的Or'd crc结果
0000000000010101 (0 x15)
=
0000000000110101 (0 x35)
所以我需要把我的地址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替换发送的内容的低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的地址调用时,返回要插入的5位CRC。与结果CRC相异的地址是要发送的。如果该16位的消息被馈送给crc5h()
,并且k
等于16,则所有16位将被处理,并且如果消息被接收时没有错误,结果将始终为零。