STM32 CRC硬件单元

STM32 CRC硬件单元

STM32采用的CRC校验模块使用的校验算法与主流CRC32校验算法不同。

下面是一个CRC在线校验网站:
http://www.ip33.com/crc.html

主流32位校验算法包括CRC-32 和 CRC-32/MPEG-2两种,而STM32采用的校验算法与这两种都不同,尽管形式上很像CRC-32/MPEG-2,但STM32是32为逐位计算的,而主流算法都是按字节计算的。

STM32CRC权值为0x4C11DB7,初始值为0xFFFFFFFF,,输入值和输出值不需要反转,输出值不需要异或运算,形式和 CRC-32/MPEG-2相同,但计算结果却不同。

以下为官方文档中给出的CRC计算单元的C语言描述:

    DWORD dwPolynomial= 0x04c11db7;
    DWORD cal_crc(DWORD *ptr, int len)
    {
       DWORD xbit;
       DWORD data;
       DWORD CRC= 0xFFFFFFFF; // init
       while (len--)
       {
           xbit=1 << 31;
           data= *ptr++;
           for (int bits= 0; bits< 32; bits++)
           {
               if(CRC & 0x80000000)
               {
                    CRC <<= 1;
                    CRC ^= dwPolynomial;
               }
               else
                    CRC <<= 1;
               if (data & xbit)
                   CRC ^= dwPolynomial;
               xbit >>= 1;
          }
     }
     return CR;
}

以下为C#中CRC-32/MPEG-2算法:

private UInt32 CRC32_MPEG_2(uint[] data, int length)
{
    uint i;
    UInt32 crc = 0xffffffff, j = 0;
    while ((length--) != 0)
    {
        crc ^= (UInt32)data[j] << 24;
        j++;
        for (i = 0; i < 8; ++i)
        {
            if ((crc & 0x80000000) != 0)
                crc = (crc << 1) ^ 0x04C11DB7;
            else
                crc <<= 1;
        }
    }
    return crc;
}

此代码和上述网址中CRC-32/MPEG-2计算结果一致。

以下是笔者根据STM32官方CRC单元C语言代码更改的C#代码:

UInt32 cal_crc(byte []ptr)
{
    UInt32 data1 = 1;
    UInt32 xbit;
    UInt32 data;
    UInt32 CRC = 0xffffffff;
    uint[] CRC32_Data;
    int len = ptr.Length;
    CRC32_Data = new uint[len];
    for (int i = 0; i < len; i++)
        CRC32_Data[i] = ptr[i];
    for (int i = 0; i < len; i++)
    {
        xbit = data1 << 31;
        data = CRC32_Data[i];
        for (int bits = 0; bits < 32; bits++)
        {
            if ((CRC & 0x80000000) != 0)
            {
                CRC = (CRC << 1) ^ 0x04C11DB7;
            }
            else
            {
                CRC = CRC << 1;
            }
            if ((data & xbit) != 0)
            {
                CRC = CRC ^ 0x04C11DB7;
            }
            xbit >>= 1;
        }
    }
    return CRC;
}

计算结果和STM32计算结果一致。
STM32F10x、FL1x、F2x、F4x系列CRC模块使用起来比较简单,只需调用官方库中的函数:

//使能CRC模块时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
//复位CRC寄存器为初始值
CRC_ResetDR();
//计算data32位数组CRC校验值
CRC1 = CRC_CalcBlockCRC(data, length);
//计算一个32为数的CRC校验值
x=CRC_CalcCRC(Data);

而STM32F0x、F30x、F37x系列比较复杂,可以更改CRC校验多项式。

笔者根据C#CRC算法和STM32F103硬件CRC单元组成上位机和下位机通讯,校验结果相同。

你可能感兴趣的:(STM32,硬件CRC,C#CRC算法)