AS32系列MCU芯片中CRC计算模块的应用介绍

电子说

1.4w人已加入

描述

在单片机驱动的电子系统中,从智能传感器、家电控制模块到工业可编程逻辑控制器(PLC)、汽车电子控制单元(ECU),数据传输与存储的完整性直接决定系统可靠性——单字节数据错误可能引发传感器信号误判、执行器动作异常甚至整个控制系统宕机。循环冗余校验(CRC)作为一种高效的错误检测技术,如同数据传输与存储过程中的"安全校验屏障",持续保障MCU与外部设备交互数据的准确性。本文将系统阐述国科安芯推出的AS32系列MCU芯片中的CRC计算单元的基本功能、实现方式及其典型应用场景。

芯片

一、CRC计算单元的基本****功能

CRC的核心是一种基于多项式运算的 错误检测算法 ,其基本原理为:将待校验数据序列视为二进制多项式D(x),选取一个预先定义的生成多项式G(x)(通常由协议标准规定),通过模2除法运算计算D(x)×x^k与G(x)的余数R(x),该余数即为CRC校验码(k为生成多项式的最高次幂)。数据发送端将原始数据与CRC校验码一同传输,接收端采用相同的生成多项式对接收数据进行运算,若运算结果与接收的CRC校验码一致,则判定数据传输无误;若不一致,则表明数据存在干扰或篡改,需启动重传或错误处理机制。

AS32系列MCU芯片的CRC计算模块是保障数据完整性的核心外设,其设计遵循主流MCU 的CRC 架构,典型功能包括:

①支持CRC-7/CRC-8/CRC-16/CRC-32 多种标准校验模式;

②可编程生成多项式(如CRC-32 支持0x04C11DB7 标准多项式,CRC-16 支持 0x8005/0x3D65等);

③支持输入/ 输出数据反转(RefIn/RefOut)、异或值(XOROut)配置;

④输入缓冲器可避免计算期间发生总线阻塞;

芯片

在MCU应用场景中,常用的CRC校验规格包括 CRC8(8位校验码)、CRC16(16位校验码)及CRC32(32位校验码) 。校验码位数与错误检测能力正相关——位数越多,对随机错误和突发错误的检测率越高,但相应的硬件资源占用开销也随之增加。

二、AS32系列MCU芯片****中CRC校验的实现方式
芯片

1. 内置的“校验加速器”

这是一个独立的数字逻辑电路,专门负责CRC运算,不需要CPU干预。开发者只需通过寄存器配置多项式、初始值等参数,再把数据地址传给模块,硬件就会自动计算并输出结果。

优点 :速度极快(4 个 APB 时钟周期完成32位CRC计算)、输入缓冲器中可立即写入第二个数据,无需因之前的CRC 计算而等待任何等待状态;

缺点 :依赖MCU硬件,参数配置需严格遵循芯片手册。

适合场景:高速通信(CAN、USB、以太网)、大数据存储(Flash、SD卡)、实时控制系统(工业电机、汽车电子)等对性能要求高的场景。

2.CRC****单元的使用方法

2.1 软件配置

关键术语说明:

CRC_Size:指参与 CRC 计算的数据长度,单位通常为字节(需根据实际硬件配置确认);CRC_OXOR: 用于对最终 CRC 结果进行异或操作;OReverse(Output Reverse):输出数据反转(如将 32 位结果的 bit31 与 bit0 交换);IReverse(Input Reverse):输入数据反转(包括位反转、半字反转、全字反转);POLYSIZE:多项式宽度类型,常见值(CRC-7/CRC-8/CRC-16/CRC-32);CRC_INIT:CRC 计算的初始值;CRC_Poly:CRC 多项式系数;CRC_XOR:异或值。

/* Initializes the CRC */
void CRC_Config(uint32_t SIZE,uint32_t OXOR_State,uint32_t OREVERSE_State,uint32_t IReverse_State,uint32_t PolySize, uint32_t INIT,uint32_t Poly,uint32_t XOR)**
{
CRC_Reset();
CRC_StructInit(&CRC_InitStructure);

CRC_InitStructure.CRC_Size = SIZE;
CRC_InitStructure.CRC_OXOR = OXOR_State;
CRC_InitStructure.CRC_OReverse = OREVERSE_State;
CRC_InitStructure.CRC_IReverse = IReverse_State;
CRC_InitStructure.CRC_PolySize = PolySize;
CRC_InitStructure.CRC_INIT = INIT;
CRC_InitStructure.CRC_Poly = Poly;
CRC_InitStructure.CRC_XOR = XOR;
CRC_Init(&CRC_InitStructure);

}

2.2功能调用

针对于不同数据宽度的数据块,可选择对应的函数进行CRC计算。

/*

 * Function:        CRC_CalcCRC

 * Description:     Computes the 32-bit CRC of a given data word.

 * Param:           Data: data word to compute its CRC.

 * Return:          32-bit CRC.

 */

uint32_t CRC_CalcCRC(uint32_t Data)

{

    /* Write the data to the CRC Data register */

    CRC- >DR = Data;

 

    /* Return the CRC value */

    ****return**** CRC- >DR;

}

 

/*

 * Function:        CRC_CalcWordBlockCRC

 * Description:     Computes the 32-bit CRC of a given buffer of data word(32-bit).

 * Param:           pBuffer: pointer to the buffer containing the data to be computed.

 *                  BufferLength: length of the buffer to be computed.

 * Return:          32-bit CRC.

 */

uint32_t CRC_CalcWordBlockCRC(uint32_t *pBuffer, uint32_t BufferLength)

{

    uint32_t index = 0;

 

     ****for**** (index = 0; index < BufferLength; index++)

    {

        CRC- >DR = pBuffer[index];

    }

 

    ****return**** (CRC- >DR);

}

 

/*

 * Function:        CRC_CalcHalfBlockCRC

 * Description:     Computes the 16-bit CRC of a given buffer of data halfword(16-bit).

 * Param:           pBuffer: pointer to the buffer containing the data to be computed.

 *                  BufferLength: length of the buffer to be computed.

 * Return:          32-bit CRC.

 */

uint32_t CRC_CalcHalfBlockCRC(uint16_t *pBuffer, uint32_t BufferLength)

{

    uint32_t index = 0;

 

     ****for**** (index = 0; index < BufferLength; index++)

    {

        CRC- >DR = pBuffer[index];

    }

 

    ****return**** (CRC- >DR);

}

 

/*

 * Function:        CRC_CalcByteBlockCRC

 * Description:     Computes the 8-bit CRC of a given buffer of data byte(8-bit).

 * Param:           pBuffer: pointer to the buffer containing the data to be computed.

 *                  BufferLength: length of the buffer to be computed.

 * Return:          32-bit CRC.

 */

uint32_t CRC_CalcByteBlockCRC(uint8_t *pBuffer, uint32_t BufferLength)

{

    uint32_t index = 0;

 

     ****for**** (index = 0; index < BufferLength; index++)

    {

        CRC- >DR = pBuffer[index];

    }

 

    ****return**** (CRC- >DR);

}

MCU****中CRC的4个典型应用场景

从日常家电到工业设备,CRC的身影无处不在:

传感器数据校验 :温湿度传感器通过单总线发送数据时,末尾会带1字节CRC8校验码,用硬件CRC快速验证,避免因电磁干扰导致“25℃”变成“85℃”的误判问题;

工业通信协议 :MODBUS-RTU协议规定,每个指令帧末尾必须附加2字节CRC16校验码,通过硬件CRC实时验证,确保控制指令准确传递到变频器、伺服电机;

Flash存储校验 :用户配置数据(如家电的亮度、音量参数)存在Flash时,会同时存储数据的CRC值;读取时用硬件CRC校验,防止Flash擦写次数过多导致数据出错;

汽车电子控制 :汽车行业在与气囊、ABS系统通信时,需要用CRC32校验关键数据,一旦检测到错误立即触发安全机制,避免事故风险。
、开发中用CRC的3个“避坑指南”

用好CRC的关键是“细节”,这3个问题一定要注意:

  1. 参数必须“对齐” :发送方和接收方的CRC参数(多项式、初始值、输入/输出反转、最终异或值)必须完全一致。比如MODBUS-RTU用CRC16/IBM(多项式0x8005,初始值0xFFFF),若一方用错多项式,校验必失败;
  2. 字节序别搞反 :多字节数据(如uint32_t)计算CRC前,要统一字节序。AS32系列MCU芯片是小端机,把0x12345678存到内存是0x78 0x56 0x34 0x12,确保不同设备间结果一致;
  3. 硬件配置看手册 :不同MCU的硬件CRC模块寄存器略有差异——开发前一定要查芯片手册,避免配置错误。

字节序检测方法 :多字节数据CRC计算前需明确MCU字节序,可通过C语言共用体(union)检测——利用共用体成员共享内存的特性,定义包含多字节整数(如uint32_t)和单字节数组(uint8_t[4])的共用体,赋值多字节整数(如0x12345678)后读取单字节数组首元素:若为0x78则为小端(低字节存低地址),若为0x12则为大端(高字节存低地址)。检测代码示例如下:

union
{
uint32_t value;
uint8_t bytes[4];
} endian_test;

endian_test.value = 0x12345678;
if (endian_test.bytes[0] == 0x78)
{
Printf("Little-Endian");
}
else if (endian_test.bytes[0] == 0x12)
{
Printf("Big-Endian");

}

在MCU系统中,CRC不像其他外设那样“显眼”,却是保障数据可靠性的“基础安全网”。硬件CRC则为高性能、高安全需求“保驾护航”。理解CRC的原理、选型和应用细节,能让你的MCU项目更稳定、更可靠——毕竟,对电子设备来说,“数据没错”是一切功能的前提。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分