CRC-16 0x8005多项式,从C到C#.SOS

Ale*_*123 0 c c# crc

我有这个C代码块,我不能为我的生活理解.我需要为我发送给该方法的某个字节数组计算CRC-16,它应该给出msb(最高有效字节)和lsb(最低有效字节).我还获得了一个C编写的应用程序来测试一些功能,该应用程序还为我提供了发送内容和通过COM端口接收的内容的日志.

有点奇怪的是,我输入了我在日志中找到的这个在线计算器的十六进制字符串,但它给了我不同的结果.

我把这个方法翻译成C#,但我不明白某些方面:

  1. 什么是pucPTR在那里做(它不是在其他地方使用)?
  2. 2行代码是什么意思,第一行是什么?
  3. 为什么在第二个短的"i"是<= 7,不应该<= 8?
  4. if语句中的最后一行意味着usCRC实际上是ushort 8005?

这是代码块:

unsigned short CalculateCRC(unsigned char* a_szBufuer, short a_sBufferLen)
{
    unsigned short usCRC = 0;
    for (short j = 0; j < a_sBufferLen; j++)
    {
        unsigned char* pucPtr = (unsigned char*)&usCRC;
        *(pucPtr + 1) = *(pucPtr + 1) ^ *a_szBufuer++;
        for (short i = 0; i <= 7; i++)
        {
            if (usCRC & ((short)0x8000))
            {
                usCRC = usCRC << 1;
                usCRC = usCRC ^ ((ushort)0x8005);
            }
            else
                usCRC = usCRC << 1;
        }
    }
    return (usCRC);
}
Run Code Online (Sandbox Code Playgroud)

这是我转换为字节数组并发送到方法的十六进制字符串:02 00 04 a0 00 01 01 03

这是应该从CRC演算中得出的结果:06 35

我给出的文件说这是整个数据的CRC16 IBM(msb,lsb).

有人可以帮忙吗?我已经坚持了一段时间了.

任何代码大师都能够将C方法转换为C#?显然我不具备这样的资源.

Lun*_*din 5

首先,请注意,与C相比,^运算符意味着按位异或.

  1. 什么是pucPTR在那里做(它不是在其他地方使用)?
  2. 2行代码是什么意思,第一行是什么?

通过它的外观导致错误.它仅用于获取FCS的两个字节中的一个,但代码是以依赖于endianess的方式编写的.

在处理校验和算法时,Endianess非常重要,因为它们最初是为硬件移位寄存器设计的,它们首先需要MSB,即大端.另外,CRC通常意味着数据通信,并且数据通信意味着发送方,协议和接收方之间可能具有不同的字节顺序.

我猜这个代码只是为小端机器编写的,目的是用ms字节进行异或.代码指向第一个字节,然后使用+1指针算法到达第二个字节.更正后的代码应该类似于:

uint8_t puc = (unsigned int)usCRC >> 8;
puc ^= *a_szBufuer;
usCRC = (usCRC & 0xFF) | ((unsigned int)puc << 8);
a_szBufuer++;
Run Code Online (Sandbox Code Playgroud)

对unsigned int的强制转换可以通过隐式整数提升来防止意外事件.


  1. 为什么在第二个短的"i"是<= 7,不应该<= 8?

我认为这是正确的,但更可读的是它可以写​​成i < 8.

  1. if语句中的最后一行意味着usCRC实际上是ushort 8005?

不,这意味着用多项式0x8005对您的FCS进行异或.看到这个.

我给出的文件说这是CRC16 IBM

是的它有时被称为.虽然我记得,"CRC16 IBM"也涉及到最终结果的一些反转(?).我仔细检查一下.


总的来说,请小心这段代码.无论谁编写它,都没有太多关于endianess,整数签名和隐式类型促销的线索.这是业余级代码.您应该能够在网上找到相同CRC算法的更安全,便携的专业版本.


关于这个主题的非常好的阅读是CRC无痛指南.