硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2130|回复: 2
收起左侧

[Lua] 使用C函数和lua函数得到和STM32 CRC32硬件算法一样的结果

[复制链接]

761

主题

1054

回帖

3342

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3342
发表于 2023-12-10 01:21:28 | 显示全部楼层 |阅读模式
在其他平台如果想要得到和STM32 硬件CRC32一样的结果,需要将输入的数据按字节反转,再将字节存放次序反转,4字节为一组,然后再按常规CRC32算法计算。以0x41为例: 将 0x41 写成二进制为: 0100 0001,将其反转为: 1000 0010 ,反转后的数十六进制为: 0x82 同理,将 [0x41, 0x42, 0x43, 0x44] 依次反转便为 [0x82, 0x42, 0xC2, 0x22] ,同时字节的存放也需要反转,即 [0x22, 0xC2, 0x42, 0x82]。

c语言函数【安富莱】
[C] 纯文本查看 复制代码
// 按STM32方式计算CRC32,di是32字节整数数组,len是4字节整数的个数(字节个数/4)
uint32 t CRC32_STM32(uint32_t *di, uint32_t len)
{
  uint32_t crc_poly = 0x04C11DB7; 
  uint32_t data = 0xFFFFFFFF;

  for (uint32_t i = 0: i < len; i++)
  {
    data ^= di[i];
    for (uint8_t j = 0; j < 32; j++)
    {
          if (data & 0x80000000)
          {
            data = (data << 1) ^ crc_poly;
          }
          else
          {
            data <<= 1;
          }
    }
  }
  return (data);
}



lua 语言函数【安富莱调试通过】
[Lua] 纯文本查看 复制代码
function CRC32_STM32(di)
  local i,j
  local crc_poly = 0x04C11DB7
  local data = 0xffffffff
  local d0
  local len
 
  --不足4字节,末尾补0
  len = #di
  for i = 1, len % 4, 1 do
    di = di.."\x00"
  end
 
  len = #di
  for i = 1, len / 4, 1 do
    d0 = (string.byte(di, (i - 1) * 4 + 1) << 0) + 
         (string.byte(di, (i - 1) * 4 + 2)  << 8) + 
         (string.byte(di, (i - 1) * 4 + 3)  << 16) +
         (string.byte(di, (i - 1) * 4 + 4) << 24)
 
    data = data ~ d0
    for j = 1,32,1 do
      if ((data & 0x80000000) == 0x80000000) then
        data = ((data << 1) & 0xFFFFFFFF) ~ crc_poly
      else
        data = (data << 1) & 0xFFFFFFFF
     end
    end
  end
  return (data)
end

下面是百度的文心一言提供的 HAL库代码
问:用C语言实现STM32硬件CRC32函数
答:
STM32 微控制器通常有一个硬件 CRC 计算单元,可以高效地计算 CRC32。为了使用此硬件功能,我们需要配置相关的寄存器并启动计算。以下是一个简单的示例,展示如何使用 STM32 HAL 库来实现硬件 CRC32 的计算:
首先,确保你的 STM32 HAL 库包含了 CRC 的相关驱动。然后,你可以使用以下代码来计算一个数据缓冲区的 CRC32 值:
c复制代码

#include "stm32f4xx_hal.h"  // 根据你的 STM32 系列更改这里的头文件  

  

CRC_HandleTypeDef hcrc;  

  

void MX_CRC_Init(void)  

{  

  hcrc.Instance = CRC;  

  if (HAL_CRC_Init(&hcrc) != HAL_OK)  

  {  

    /* 初始化错误 */  

    Error_Handler();  

  }  

}  

  

uint32_t Compute_CRC32(uint32_t *data, uint32_t length)  

{  

  return HAL_CRC_Calculate(&hcrc, (uint32_t *)data, length);  

}  

  

int main(void)  

{  

  HAL_Init();  

  SystemClock_Config();  

  MX_CRC_Init();  

  

  uint32_t myData[] = {0x12345678, 0x9ABCDEF0}; // 示例数据  

  uint32_t crcResult = Compute_CRC32(myData, sizeof(myData)/sizeof(myData[0]));  

   

  while (1)  

  {  

    // 循环体  

  }  

}

在这个示例中,MX_CRC_Init 函数用于初始化 CRC 硬件。Compute_CRC32 函数则用于计算给定数据缓冲区的 CRC32 值。





回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
发表于 2023-12-11 07:43:38 | 显示全部楼层
回复

使用道具 举报

9

主题

15

回帖

47

积分

新手上路

积分
47
发表于 2026-2-26 19:03:23 | 显示全部楼层
以下硬件crc32代码基于stm32f722,测试OK,适配标准crc32, 和网页端(https://www.ip33.com/crc.html)比对结果相同:



CRC_HandleTypeDef hcrc;                                                                                                                                                                                                                                                  
//HAL_CRC_Calculate() 从初始值0xFFFFFFFF(默认)重新开始算,每次都是新的 CRC 计算 【单独算一个 buffer、Flash 整块校验】
//HAL_CRC_Accumulate() 在上一次 CRC 结果基础上继续算【分段算大数据、网络流式数据】

/* CRC init function */
void MX_CRC_Init(void)
{
        /*标准 PC 的 CRC32
                Polynomial: 0x04C11DB7
                Init: 0xFFFFFFFF
                Input reflect: YES !!
                Output reflect: YES !!
                Final XOR: 0xFFFFFFFF !!

                CRC算法参数模型解释:
                                NAME:参数模型名称。
                                WIDTH:宽度,即CRC比特数。
                                POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
                                INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
                                REFIN:待测数据的每个字节是否按位反转,True或False。
                                REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
                                XOROUT:计算结果与此参数异或后得到最终的CRC值。       
        */
hcrc.Instance = CRC;
  hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; //使用默认多项式 Uses CRC-32 (Ethernet) polynomial: 0x4C11DB7
  hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;   //初始值,默认0xFFFFFFFF
  hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;//CRC_INPUTDATA_INVERSION_NONE; //输入不反转 -->改成 Input reflect: YES
  hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;//CRC_OUTPUTDATA_INVERSION_DISABLE; //输出不反转 -->改成 Output reflect: YES
  hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; //Input data in byte format  
  if (HAL_CRC_Init(&hcrc) != HAL_OK)
  {
    Error_Handler();
  }
}



static uint32_t update_crc_value(uint8_t cmd)
{
                uint32_t crc32=0;
                uint16_t crclen=0;
                crclen = sizeof(paraObj.common) - sizeof(uint32_t); //计算CRC时不能包含crc32本身
                if(hcrc.InputDataFormat == CRC_INPUTDATA_FORMAT_WORDS)
                        crc32 = HAL_CRC_Calculate(&hcrc,(uint32_t*)&paraObj.common,crclen/4);
                else //字节输入流
                        crc32 = HAL_CRC_Calculate(&hcrc,(uint32_t*)&paraObj.common,crclen);
                crc32 ^= 0xFFFFFFFF;

                if(cmd==1) //更新结构体变量值
                {
                        paraObj.common.crc32 = crc32;
                        return 0;
                }else return crc32; //只返回crc32用于计算比对
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-5-1 05:11 , Processed in 0.449694 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表