如何使用此代码计算 CRC?

How to calculate CRC using this code?

我正在尝试在设备和我的服务器之间建立无线电通信。来自设备的数据如下所示:

fa-00-01-09-16-aa-00-14-10-01-01-00-01-16-ff-ff-ff-ff-ff-ff-cb-14

最后两个字节是 CRC。现在我需要向我的设备发送回复并计算它的 CRC。 Device's data sheet 没什么好说的,它只提供了C函数来计算它,但我很难理解我应该为这个函数提供什么

unsigned int CRC_Check(unsigned char *ucCRC_Buf, unsigned char ucBufLength)
{
    unsigned int uiX, uiY, uiCRC;
    unsigned char ucStart = 0;
    uiCRC = 0xFFFF; //set all 1

    if (ucBufLength <= 0 || ucStart > ucBufLength)
    {
        uiCRC = 0;
    }
    else
    {
        ucBufLength += ucStart;

        for (uiX = (unsigned int)ucStart; uiX < ucBufLength; uiX++)
        {
            uiCRC = (unsigned int)(uiCRC ^ ucCRC_Buf[uiX]);

            for (uiY = 0; uiY <= 7; uiY++)
            {
                if((uiCRC & 1) != 0)
                    uiCRC = (unsigned int)((uiCRC >> 1)^0xA001);
                else
                    uiCRC = (unsigned int)(uiCRC >> 1);
            }
        }
    }

    return uiCRC;
}

数据sheet还说“CRC校验是对数据包进行的,不包括起始码和校验码”,意思是第一个字节(0xFA)和最后两个字节字节(CRC)。

现在我试图了解它对 unsigned char *ucCRC_Bufunsigned char ucBufLength 的期望。从我的主要我想做的:

unsigned int crc = CRC_Check("00010916aa0014100101000116ffffffffffff",38);
printf("%d\n", crc);

这与开头的字符串相同(没有第一个和最后两个字节),我期待 CB14(十六进制)。但它给出了不同的数字(54016(十进制),即 D300(十六进制))。

知道我做错了什么吗?

假设服务器发送的数据为Hexadecimal格式。

您将一个字符串传递给函数,这给您带来了错误的结果。

正确的验证方式是:

unsigned char data[] = {0x00,0x01,0x09,0x16,0xaa,0x00,0x14,0x10,0x01,0x01,0x00,0x01,0x16,0xff,0xff,0xff,0xff,0xff,0xff}

unsigned int CRC = CRC_Check(&data[0],19);

可能你必须传递字节本身,而不是它们的十六进制表示。

改变

unsigned int crc=CRC_Check("00010916aa0014100101000116ffffffffffff",38);

unsigned int crc=CRC_Check("\x00\x01\x09\x16\xaa\x00\x14\x10\x01\x01\x00\x01\x16\xff\xff\xff\xff\xff\xff", 19);

注意只有19个字节。 (感谢@alk)