STM32硬件CRC的使用说明

本文对应STM32G0系列
STM32硬件的CRC不占用MCU的计算资源,和软件查表计算消耗的存储空间。但其结果与平常使用的CRC不一样,导致很多人还是在用软件计算CRC。
其实结果的差别,只是由于计算方式导致的,调整计算方式以后也可以输出普通计算的结果。

软件计算CRC16

u16 LL_crc16_calculator(u8* data, u16 len)
{ 
  u16 tmp = 0xffff;
  u16 ret1 = 0;

  for(int n = 0; n < len; n++)
  {
    tmp = data[n] ^ tmp;
    for(int i = 0; i < 8; i++)  /*此处的8 -- 指每一个char类型有8bit,每bit都要处理*/
    {
      if(tmp & 0x01)
      {
        tmp = tmp >> 1;
        tmp = tmp ^ 0xa001;   //多项式0x8005的倒序
      }   
      else
        tmp = tmp >> 1;
    }   
  } 
  return tmp;
}

软件计算CRC32

u32 LL_crc32_calculator(u8* data, u16 len)
{ 
  u32 tmp = 0xffffffff;
  u32 ret1 = 0;

  for(int n = 0; n < len; n++)
  {
    tmp = (data[n]) ^ tmp;
    for(int i = 0; i < 8; i++)  /*此处的8 -- 指每一个char类型有8bit,每bit都要处理*/
    {
      if(tmp & 0x01)
      {
        tmp = tmp >> 1;
        tmp = tmp ^ 0xedb88320;   //多项式0x04c11db7的倒序后是0xedb88320
      }   
      else
        tmp = tmp >> 1;
    }   
  } 
  tmp = ~tmp;
  return tmp;
}

软件与硬件计算的异同

与普通计算方式相同,以CRC32举例,其默认多项式也是
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1,但也可以自定义。
计算的初值不同:STM32为0,普通CRC计算为0xffffffff
计算的顺序不同:STM32从最低位开始计算,普通CRC从最高位开始计算
输出结果:最高位到最低位,与普通CRC刚好相反,而且普通CRC的输出结果为计算结果与0xffffffff异或后输出,STM32就少了这个异或,或者说取反操作。

CubeMX处理

知道了不同之处,接下来的处理就很简单了。在CRC32的设置中按下图,其他系列参照上述软件计算过程,进行对应修改即可

stm32 cubemx的Rcc显示感叹号_crc

编程

u8 crc_buf[6] = {0xBE, 0xEF, 0x55, 0xaa, 0xcc, 0xdd};

u32 calculate_crc32(u8 *pdata, u16 len)
{
  u32 crc=0;
 
  //因为主流CRC计算是结果与0xffffffff异或后再输出,而STM32并没有,所以这里要加上异或
  //以下2行代码等效,用自己看得惯的方式就行
  crc = HAL_CRC_Calculate(&hcrc, (u32 *)pdata, len)^0xffffffff;
  crc =~HAL_CRC_Calculate(&hcrc, (u32 *)pdata, len);
  
  return crc;
}

验证

硬件crc的结果为0x8c9792a5

打开 http://www.ip33.com/crc.html,进行结果验证

stm32 cubemx的Rcc显示感叹号_stm32_02


结果相符。

CRC16的计算方法又有区别

对于CRC16有些不同,要计算CRC16时,第1个参数选Disable,然后多项式可以自定义

而且计算方法也和CRC32不同,注意看区别

stm32 cubemx的Rcc显示感叹号_循环冗余校验码_03


设置或更改的内容如下:

默认的多项式是不对的,常规应该是0x8005,按位设置好就是X15+X2+X0

默认的初值置0

输入反转,输出不反。

计算结果不异或。

crc = HAL_CRC_Calculate(&hcrc, (u32 *)pdata, len);

结果验证:

对于0x07, 0x02, 0x00, 0x10, 0x00,硬件CRC计算结果为0x9D1D

stm32 cubemx的Rcc显示感叹号_crc_04


结果相符

MODBUS

MODBUS一般是8个字节,其中CRC16占用最后的2个字节,正文共6个字节,在这里也示例一下

stm32 cubemx的Rcc显示感叹号_stm32_05


代码如下:

crc16 = HAL_CRC_Calculate(&hcrc, (u32*)uart2_receive_buf, 6);

stm32 cubemx的Rcc显示感叹号_循环冗余校验码_06

stm32 cubemx的Rcc显示感叹号_单片机_07

当然有很多种计算CRC的参数模型,按照上面的方法套一下即可。

CubeMX使用入门教程

从私信和留言发现,很多朋友对CubeMX的使用并不熟悉,找不到CRC或相关功能,为此我专门做了一个教程,点开这里可以看:嵌入式开发–CubeMX使用入门教程,里面有使用方法。