第十八章 CRC

第十八章 CRC

目录

第十八章 CRC

1 CRC简介

2 CRC主要特性

3 CRC功能描述

4 CRC寄存器CRC 计算单元包括 2 个数据寄存器和 1 个控制寄存器

4.1 数据寄存器(CRC_DR)

4.2 独立数据寄存器(CRC_IDR)

4.3 控制寄存器(CRC_CR)

4.4 CRC 寄存器映像

5 例程设计

5.1 CRC_DifferentCrcMode例程

6 下载验证

6.1 CRC_DifferentCrcMode例程


1 CRC简介

循环冗余校验(CRC)计算单元是根据固定的生成多项式得到任一 172 位全字的 CRC 计算结果。在其他的应用中,CRC 技术主要应用于核实数据传输或者数据存储的正确性和完整性。标准EN/IEC60335-1 即提供了一种核实闪存存储器完整性的方法。CRC 计算单元可以在程序运行时计算出软件的标识,之后与在连接时生成的参考标识比较,然后存放在指定的存储器空间。

2 CRC主要特性

  • 使用 CRC-32(以太网)多项式:0x4C11DB7
    • X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X4+X2+X+1
  • 一个 32 位数据寄存器用于输入/输出
  • CRC 计算时间:4 个 AHB 时钟周期(HCLK)
  • 通用 8 位寄存器(可用于存放临时数据)

下图为 CRC 计算单元框图:

CRC 计算单元框图

3 CRC功能描述

CRC 计算单元含有 1 个 32 位数据寄存器:

  • 对该寄存器进行写操作时,作为输入寄存器,可以输入要进行 CRC 计算的新数据。
  • 对该寄存器进行读操作时,返回上一次 CRC 计算的结果。

每一次写入数据寄存器,其计算结果是前一次 CRC 计算结果和新计算结果的组合(对整个 32 位字进行 CRC 计算,而不是逐字节地计算)。

在 CRC 计算期间会暂停 CPU 的写操作,因此可以对寄存器 CRC_DR 进行背靠背写入或者连续地写-读操作。可以通过设置寄存器 CRC_CR 的 RESET 位来重置寄存器 CRC_DR 为0xFFFF FFFF。该操作不影响寄存器 CRC_IDR 内的数据。

4 CRC寄存器CRC 计算单元包括 2 个数据寄存器和 1 个控制寄存器

4.1 数据寄存器(CRC_DR)

地址偏移:0x00

复位值:0xFFFF FFFF

4.2 独立数据寄存器(CRC_IDR)

地址偏移:0x04

复位值:0x0000 0000

4.3 控制寄存器(CRC_CR)

地址偏移:0x08

复位值:0x0000 0000

4.4 CRC 寄存器映像

下表列出了 CRC 的寄存器映像和复位值:

CRC 计算单元寄存器映像和复位值

5 例程设计

5.1 CRC_DifferentCrcMode例程

1.宏定义与结构体:定义了不同 CRC 模式的预期结果,创建了CRC_ResultInfo结构体用于存储 CRC 模式名称和预期结果,同时定义了待计算 CRC 的数据缓冲区Buff。

2.UART 模块:UART_Configuration函数:使能 USART1 和 GPIOA 时钟,配置 GPIO 引脚,初始化 USART 参数(波特率、数据位、停止位等),最后使能 USART1。

  • 重定向printf函数:通过SER_PutChar和fputc函数将printf输出重定向到 USART1,方便输出调试信息。

3.CRC 测试模块:CRC_DifferentModeTest函数:遍历不同的 CRC 模式,对Buff缓冲区的数据进行 CRC 计算。每次计算前重置 CRC 数据寄存器,将计算结果与预期结果比较,若一致则输出 “Right”,不一致则输出 “Error” 并显示预期结果。

// CRC多模式测试函数
void CRC_DifferentModeTest(void)
{
    uint32_t crcresult = 0; // 存储实际计算结果
    uint8_t  i;

    // 遍历所有CRC测试用例
    for (i = 0; i < sizeof(CRCResult) / sizeof(CRC_ResultInfo); i++)
    {
        CRC_ResetDR(); // 重置CRC数据寄存器(清除之前的计算结果)

        // 计算CRC值(参数:CRC模式、数据缓冲区、数据长度(字计数))
        crcresult = CRC_CalcBlockCRC(CRC_16_IBM + i, Buff, sizeof(Buff) / 4);

        // 比较实际结果与预期结果
        if (CRCResult[i].CRCResultData == crcresult)
        {
            printf("%s Right.\n", CRCResult[i].Str); // 输出测试通过信息
        }
        else
        {
            // 输出测试失败信息及预期结果
            printf("%s Error.\n", CRCResult[i].Str);
            printf("%s Error Result is 0x%x\n", CRCResult[i].Str, CRCResult[i].CRCResultData);
        }
    }
}

4.主函数模块:使能 CRC 时钟,初始化延时函数和 UART。

int main(void)
{
    RCC_ClocksTypeDef clocks; // 系统时钟结构体

    // 1. 使能CRC时钟(AHB总线)
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);

    // 2. 基础初始化:延时函数、串口
    delay_init();
    UART_Configuration(115200);

    // 3. 获取并打印系统时钟信息
    RCC_GetClocksFreq(&clocks);
    printf("\nSYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",
           (float)clocks.SYSCLK_Frequency / 1000000,
           (float)clocks.HCLK_Frequency / 1000000,
           (float)clocks.PCLK1_Frequency / 1000000,
           (float)clocks.PCLK2_Frequency / 1000000,
           (float)clocks.ADCCLK_Frequency / 1000000);

    // 4. 打印测试提示
    printf("CRC Different Mode Test.\n");

    // 5. 执行CRC测试
    CRC_DifferentModeTest();

    // 6. 主循环(保持程序运行)
    while (1);
}
  • 获取并输出系统时钟频率信息。
  • 输出测试提示信息。
  • 调用CRC_DifferentModeTest函数进行 CRC 测试。
  • 进入无限循环,保持程序运行。

6 下载验证

6.1 CRC_DifferentCrcMode例程

程序启动阶段

  • 串口输出系统时钟信息:程序启动后,会通过串口输出系统时钟的相关频率信息,包括 SYSCLK、HCLK、PCLK1、PCLK2 和 ADCCLK 的频率,帮助确认系统时钟配置是否正确。
  • 显示测试提示信息:紧接着输出测试提示信息,表明开始进行不同模式的 CRC 测试。

CRC 测试阶段

  • 遍历不同 CRC 模式进行测试:程序会依次对多种 CRC 模式(如 CRC_16_IBM、CRC_16_MAXIM 等)进行测试。
  • 输出测试结果:对于每种 CRC 模式,会计算给定数据(Buff数组)的 CRC 值,并将其与预设的预期结果进行比较。
    • 计算结果正确:若计算得到的 CRC 值与预期结果一致,串口会输出相应模式的测试结果为 “Right”。
    • 计算结果错误:若计算得到的 CRC 值与预期结果不一致,串口会输出相应模式的测试结果为 “Error”,并显示该模式下的预期结果。

程序持续运行

  • 进入无限循环:完成所有 CRC 模式的测试后,程序会进入无限循环,保持运行状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值