Diving into the STM32 HAL-----Cyclic Redundancy Check笔记

        在数字系统中,数据完全有可能被损坏,特别是当它流经通信介质时。在数字电子学中,消息是等于 0 或 1 的比特流,当这些比特中的一个或多个在传输过程中意外更改时,它就会损坏。因此,消息中始终有一些额外的数据用于检测原始消息是否已损坏。在前面,我们分析了与数据传输相关的一种早期错误检测形式: 奇偶校验位是添加到消息中的附加位,用于跟踪等于 1 的位数是否为奇数或偶数(取决于奇偶校验的类型)。但是,如果两个或多个 bit 同时更改,则此方法无法检测到错误。

        循环冗余校验 (CRC) 是一种广泛使用的技术,用于检测数字数据在传输和存储过程中的错误。在 CRC 方法中,几个校验位(称为校验和)被附加到正在传输的消息中。接收方可以确定校验位是否与数据一致,以便在传输过程中发生错误时以一定概率进行断言。如果是这样,接收方可以要求发送方再次重新传输消息。

        此技术也适用于某些数据存储设备,例如硬盘驱动器。在这种情况下,磁盘上的每个块都有一定的校验位,硬件可能会在检测到错误时自动启动块的重新读取,或者可能会将错误报告给软件。需要强调的是,CRC 是识别消息损坏的好方法,但不是在检测到错误时进行更正的好方法。

        由于许多通信外设和协议(如以太网、MODBUS 等)都使用 CRC 方法,在微控制器中很常见,专用硬件外设能够计算字节流的 CRC 校验和,从而将 CPU 从软件中执行此操作中解放出来。所有 STM32 微控制器都提供专用的 CRC 外设,本章简要介绍如何使用相应的 CubeHAL 模块。

        像往常一样,在进入实现细节之前,我们将首先简要介绍 CRC 技术背后的数学原理。zlib.net/crc_v3.txt

1、CRC 计算简介

        CRC 技术基于众所周知的多项式算术特性。为了计算比特流的校验和,该消息被视为一个多项式,该多项式除以另一个固定多项式(称为多项式生成器)。此操作的余式就是校验和,添加到原始消息中。接收方将使用它以及多项式生成器来检查消息是否正确。

        在实践中,所有 CRC 方法都使用 GF(2ⁿ) 中的多项式。GF(pⁿ) 代表伽罗瓦域,也称为有限域,即具有有限元素数量的域。伽罗瓦域是定义乘、加、减、除运算并满足某些基本规则的集合。有限域的最常见示例由整数模 p 给出,其中 p 是素数。在我们的例子中,p 等于 2,这意味着当 n=1 时,GF(2ⁿ) 字段只包含两个元素:0 和 1。

        在 GF(2ⁿ) 中,加法和减法以 2 为模数执行,也就是说,它们对应于 XOR 逻辑运算。

乘法对应于 AND 逻辑运算。

        GF(2ⁿ) 中的多项式是单个变量 x 中的多项式,其系数为 0 或 1。CRC 技术将数据消息的位解释为 GF(2ⁿ) 中多项式的系数,其度数等于 n − 1,其中 n 是消息的长度。例如,假设消息 11100110 的长度等于 8,这对应于多项式:

        如前所述,在 GF(2ⁿ) 中,加法和减法对应于 XOR 逻辑运算。这意味着多项式 x 4 + x 3 + 1 和 x 3 + x + 1 之和等于 x 4 + x。(在普通代数中,加法等于 x 4 + 2x 3 + x + 2。)显然,这两个多项式的减法也是一样。GF(2ⁿ) 中的多项式乘法,像往常一样,很像乘以十进制整数,跟踪 x 的幂而不是小数位。例如,将前两个多项式相乘,得到:

第一个项中的每个项都乘以第二个项中的每个项,然后我们按照 GF(2ⁿ) 中的加法规则将它们相加。

        在 GF(2ⁿ) 中,一个多项式除以另一个多项式类似于整数的长除法(余数),只是没有借用或进位。例如,让我们将多项式 x 7 + x 6 + x 5 + x 2 + x 除以多项式 x 3 + x + 1。

        我们首先将被除数的第一项除以除数的最高项(即具有最高 x 次方的项,在本例中为 x 3 )。接下来,我们将除数乘以刚刚获得的结果(最终商的第一项)。

        现在我们应用了 GF(2ⁿ) 中的减法规则,从原始被除数的适当项中减去刚刚得到的乘积。

        我们重复前面的步骤,只是这次使用刚刚写为减法后被除数的两个项。

        该过程一直持续到获得的被除数低于除数的幂次。我们这样获得了除法的余数,它表示要附加到原始消息的校验和。

        接收方有两种方法可以评估传输的正确性。它可以从接收到的数据的前 n 位计算校验和,并验证它是否与最后 r 个接收到的位一致。或者,按照通常的做法,接收器可以将所有接收到的位除以多项式生成器,并检查 r 位余数是否为 0。

        但是,CRC 计算的确切算法通常与正常的多项式除法不同。此外,多项式生成器可以定义特定的初始和最终条件。这意味着多项式生成器不能任其更改,而是从经过充分研究http://bit.ly/293h2Hd的多项式组合中保留下来。例如,广泛采用的 CRC-32 多项式的形式为:

可以用二进制表示,序列为 00000100110000010001110110110111,用十六进制表示,数字0x04C1 1DB7。它被许多传输和存储协议采用,如以太网、串行 ATA、MPEG-2、BZip2 和 PNG。

1.1、STM32F1/F2/F4/L1 MCU 中的 CRC 计算

        多项式的长除法适合执行手动计算。但是,另一种更有效的 CRC 算法是使用按位消息 XOR 技术的多项式除法,这适合使用专用硬件电路: Shift Registers来实现。

        STM32 微控制器中 CRC 计算的过程与 CRC-32 多项式定义的算法有关,即以下:

        • 用 0xFFFF FFFF 与数据值进行 XOR 来初始化 CRC 寄存器。

        • 逐位移动输入流。如果弹出的 MSB 为 '1',则对 CRC 寄存器值与多项式生成器进行 XOR 运算。

        • 如果所有输入位都被处理,则 CRC 移位寄存器包含 CRC 值。

        假设数据值等于 10101101(0xAD),CRC 多项式等于 00010110 (0x16),STM32 MCU 实现的算法是这样工作的(上图示意图化了这个过程):

        1. CRC 寄存器的初始内容是通过 0xFF 和 0xAD 进行 XOR 运算来计算的。

        2. 由于 MSB 位为0,CRC 寄存器只是左移。

        3. 现在 CRC 寄存器的 MSB 位为 1。因此,我们首先左移寄存器,然后使用 CRC 多项式 (0x16) 执行 XOR。

        4. 由于 MSB 位为0,CRC 寄存器只是左移。

        5. 现在 CRC 寄存器的 MSB 位为1。因此,我们首先左移寄存器,然后使用 CRC 多项式 (0x16) 执行 XOR。

        6.由于 MSB 位为0,CRC 寄存器只是左移。

        7. 现在 CRC 寄存器的 MSB 位为 1。因此,我们首先左移寄存器,然后使用 CRC 多项式 (0x16) 执行 XOR。

        8. 现在 CRC 寄存器的 MSB 位为 1。因此,我们首先左移寄存器,然后使用 CRC 多项式 (0x16) 执行 XOR。

        9. 最后,MSB 再次为 0。因此,我们对 CRC 寄存器执行左移。final 值表示要添加到消息前面的校验和。

        上述算法只是 STM32 MCU 中实际实现的算法的简化。事实上,它的不同有两个主要原因:

        • CRC 多项式是固定的,对应于 CRC-32 (0x04C1 1DB7)。

        • 单个输入/输出数据寄存器为 32 位宽,CRC 校验和是在整个 32 位寄存器上计算的,而不是逐字节计算的。http://bit.ly/29303sh、http://bit.ly/293067u

        这极大地限制了此外设的有效可用性。

1.2、STM32F0/F3/F7/L0/L4/L5/G0/G4 MCU 中的 CRC 外设

        在上一段中,我们已经看到一些 STM32 MCU 提供的 STM32 外设仅限于使用 CRC-32 以太网多项式计算 CRC。此外,每次计算的处理数据大小为 32 位。在较新的 STM32 系列中,此限制已被取代。事实上,STM32F0/F3/F7/L0/L4/L5/G0/G4 MCU 提供了更高级的 CRC 外设,如下表所示。

        在这些 MCU 中,CRC 外设设计为默认与 STM32F1/F2/F4/L1 MCU 提供的更简单的 CRC 外设兼容。这意味着,在没有显式配置的情况下,设计为在 STM32F1/F2/F4/L1 MCU 上运行的代码将在 STM32F0/F3/F7/L0/L4 MCU 上运行,无需任何更改。

2、HAL_CRC 模块

        CubeHAL 提供了一个专用模块来操作 CRC 外设寄存器:HAL_CRC。CRC 外设通过使用 CRC_HandleTypeDef 结构的实例来引用。在提供最简单的 CRC 外设的 STM32F1/F2/F4/L1 MCU 中,此结构体按以下方式定义:

typedef struct {
	CRC_TypeDef *Instance; /* CRC registers base address */
	HAL_LockTypeDef Lock; /* CRC locking object */
	__IO HAL_CRC_StateTypeDef State; /* CRC communication state */
} CRC_HandleTypeDef;

        唯一相关的字段是 Instance 1,它是指向 CRC 外设描述符的指针(其基址由 CRC 宏定义)。

        相反,在 STM32F0/F3/F7/L0/L4 MCU 中,CRC_HandleTypeDef 结构体的定义方式如下:

typedef struct {
	CRC_TypeDef *Instance; /* Register base address */
	CRC_InitTypeDef Init; /* CRC configuration parameters */
	HAL_LockTypeDef Lock; /* CRC Locking object */
	__IO HAL_CRC_StateTypeDef State; /* CRC communication state */
	uint32_t InputDataFormat; /* Specifies input data format. */
} CRC_HandleTypeDef;

        唯一相关的区别是 Init 字段的存在,该字段用于配置 CRC 外设,以及 InputDataFormat 字段,该字段指定输入数据的数据大小:它可以采用下表中的值。

        为了在这些 MCU 中配置 CRC 外设,我们使用 CRC_InitTypeDef 结构的实例, 其定义如下:

typedef struct {
	uint8_t DefaultPolynomialUse; /* Indicates if default polynomial is used */
	uint8_t DefaultInitValueUse; /* Indicates if default init value is used */
	uint32_t GeneratingPolynomial; /* Set CRC generating polynomial */
	uint32_t CRCLength; /* Indicates CRC length */
	uint32_t InitValue; /* Set the initial value to start CRC computation */
	uint32_t InputDataInversionMode; /* Specifies input data inversion mode */
	uint32_t OutputDataInversionMode; /* Specifies output data (i.e. CRC) inversion mode */
} CRC_InitTypeDef;

        • DefaultPolynomialUse:这个字段指示使用的是默认多项式(即 CRC-32)还是自定义多项式。它可以采用 DEFAULT_POLYNOMIAL_ENABLE 或 DEFAULT_POLYNOMIAL_DISABLE 的值。在最后一种情况下,必须设置字段 GeneratingPolynomial 和 CRCLength。

        • DefaultInitValueUse:此字段指示是使用默认 CRC 初始化值 (即 0xFFFF FFFF) 还是自定义值。它可以采用 DEFAULT_INIT_VALUE_ENABLE 或 DEFAULT_INIT_VALUE_DISABLE 的值。在最后一种情况下,必须设置字段 InitValue。

        • GeneratingPolynomial:设置 CRC 生成多项式。7、8、16 或 32 位长值,表示多项式次数等于 7、8、16 或 32。该字段以正常表示形式书写,例如,对于 7 次多项式,X7 + X6 + X5 + X2 + 1 写0x65。

        • CRCLength:此字段表示 CRC 的长度,它可以采用下表中的值。

        • InitValue:设置自定义初始值以开始 CRC 计算。

        • InputDataInversionMode:指定是否必须反转输入数据。它可以采下用中的值。

        • OutputDataInversionMode:指定输出数据(计算的 CRC)是否必须反转。它可以采用值 CRC_OUTPUTDATA_INVERSION_DISABLE 和 CRC_OUTPUTDATA_INVERSION_ENABLE。在最后一种情况下,操作在位级别完成:例如,0x1122 3344 的输出数据转换为 0x22CC 4488。

        一旦定义 CRC_InitTypeDef 结构体的实例,并正确填充其字段,我们通过调用函数来配置 CRC 外设:

HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc);

        要计算数据缓冲区的 CRC 校验和,我们使用函数:

uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength);

它接受指向 uint32_t 数组及其长度的指针。该函数将默认 CRC 初始值设置为 0xFFFF FFFF,如果我们使用的是 STM32F0/F3/F7/L0/L4 MCU,则为指定值。相反,如果我们需要从先前计算的 CRC 作为初始值开始计算 CRC,那么我们可以使用函数:

uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength);

当我们使用小于源块的临时缓冲区计算大块数据的 CRC 校验和时,这尤其有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924184.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Swift——类与结构体

一.结构体 在swift的标准库中,大部分的类型都是结构体,比如:Int,Double,String,Array,Dictionary等等,它们都是结构体。 结构体定义如下: struct Person {var name:St…

反射泛型

反射 class 包含哪些内容? 当使用new 对象时需要构造函数是public 的,而当变成私有时再new则会报错 反射通过私有构造方法创建对象,破环单例模式 Clazz.getDeclared(构造函数,方法属性等)和直接get构造函数,方法属性等…

RHCE——SELinux

SELinux 什么是SELinux呢?其实它是【Security-Enhanced Linux】的英文缩写,字母上的意思就是安全强化Linux的意思。 SELinux是由美国国家安全局(NSA)开发的,当初开发的原因是很多企业发现,系统出现问题的原因大部分都在于【内部…

etcd、kube-apiserver、kube-controller-manager和kube-scheduler有什么区别

在我们部署K8S集群的时候 初始化master节点之后(在master上面执行这条初始化命令) kubeadm init --apiserver-advertise-address10.0.1.176 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.16.0 --service…

uniapp定义new plus.nativeObj.View实现APP端全局弹窗

为什么要用new plus.nativeObj.View在APP端实现弹窗?因为uni.showModal在APP端太难看了。 AppPopupView弹窗函数参数定义 参数一:弹窗信息(所有属性可不填,会有默认值) 1.title:"", //标题 2.content:"", //内容 3.confirmBoxCo…

一文学习开源框架OkHttp

OkHttp 是一个开源项目。它由 Square 开发并维护,是一个现代化、功能强大的网络请求库,主要用于与 RESTful API 交互或执行网络通信操作。它是 Android 和 Java 开发中非常流行的 HTTP 客户端,具有高效、可靠、可扩展的特点。 核心特点 高效…

DRM(数字权限管理技术)防截屏录屏----视频转hls流加密、web解密播放

提示:视频转hls流加密、web解密播放 需求:研究视频截屏时,播放器变黑,所以先研究的视频转hls流加密 文章目录 [TOC](文章目录) 前言一、工具ffmpeg、openssl二、后端nodeexpress三、web播放四、文档总结 前言 ‌HLS流媒体协议‌&a…

Rk3588 onnx转rknn,出现 No module named ‘rknn‘

一、操作步骤: rk3588 需要将yolo11 的模型onnx转rknn。 https://github.com/airockchip/rknn_model_zoo/tree/main/examples/yolo11 这个是用yolo11训练的模型,有80种类型。 完整下载下来后,在按文档描述下载模型下来: 然后进…

IDEA 解决Python项目import导入报错、引用不到的问题

使用Idea 23.1 专业版编写Python项目时,import 导入爆红,无法引入其他package的代码,现象如: 解决方案:Idea表头打开 File -> Project Settring 解决效果:

unity 使用UI上的数字按钮,给text添加数字,并且显示光标,删除光标前数字,

今天有个需求,输入身份证,但是不用键盘,要点击按钮输入数字,并且可以控制光标, 1、数字按钮:点击后text添加数字内容 2、删除按钮:删除光标前的一个字符 3、左箭头:移动光标向左移动…

火山引擎VeDI在AI+BI领域的演进与实践

随着数字化时代的到来,企业对于数据分析与智能决策的需求日益增强。作为新一代企业级数据智能平台,火山引擎数智平台VeDI基于字节跳动多年的“数据驱动”实践经验,也正逐步在AI(人工智能)与BI(商业智能&…

【逐行注释】自适应观测协方差R的AUKF(自适应无迹卡尔曼滤波,MATLAB语言编写),附下载链接

文章目录 自适应R的UKF逐行注释的说明运行结果部分代码各模块解释 自适应R的UKF 自适应无迹卡尔曼滤波(Adaptive Unscented Kalman Filter,AUKF)是一种用于状态估计的滤波算法。它是基于无迹卡尔曼滤波(Unscented Kalman Filter&…

LLM应用-prompt提示:RAG query重写、相似query生成 加强检索准确率

参考: https://zhuanlan.zhihu.com/p/719510286 1、query重写 你是一名AI助手,负责在RAG(知识库)系统中通过重构用户查询来提高检索效果。根据原始查询,将其重写得更具体、详细,以便更有可能检索到相关信…

Spring Boot 与 Spring Cloud Alibaba 版本兼容对照

版本选择要点 Spring Boot 3.x 与 Spring Cloud Alibaba 2022.0.x Spring Boot 3.x 基于 Jakarta EE,javax.* 更换为 jakarta.*。 需要使用 Spring Cloud 2022.0.x 和 Spring Cloud Alibaba 2022.0.x。 Alibaba 2022.0.x 对 Spring Boot 3.x 的支持在其发行说明中…

如何通过PHP爬虫模拟表单提交,抓取隐藏数据

引言 在网络爬虫技术中,模拟表单提交是一项常见的任务,特别是对于需要动态请求才能获取的隐藏数据。在电商双十一、双十二等促销活动期间,商品信息的实时获取尤为重要,特别是针对不断变化的价格和库存动态。为了满足这种需求&…

嵌入式Qt使用ffmpeg视频开发记录

在此记录一下Qt下视频应用开发的自学历程,可供初学者参考和避雷。 了解常用音频格式yuv420p、h264等了解QML,了解QVideoOutput类的使用,实现播放yuv420p流参考ffmpeg官方例程,调用解码器实现h264解码播放 不需要手动分帧。ffmpeg…

Java设计模式笔记(一)

Java设计模式笔记(一) (23种设计模式由于篇幅较大分为两篇展示) 一、设计模式介绍 1、设计模式的目的 让程序具有更好的: 代码重用性可读性可扩展性可靠性高内聚,低耦合 2、设计模式的七大原则 单一职…

dns 服务器简单介绍

dns 服务器分类: 根域名服务器顶级域名服务器权威域名服务器本地域名服务器 dns 的查询过程 国内优秀公共域名 腾讯:DNSPod-免费智能DNS解析服务商-电信_网通_教育网,智能DNS-烟台帝思普网络科技有限公司 119.29.29.29 和 182.254.118.118 阿里&#xf…

vscode中json文件的注释飘红

vscode的json文件 添加注释,提示json中不允许有注释,点编辑器最下面的json,如下图 然后选择如上图的json with comments就好了

AI PAC!PLC与AIPC通过微定制深度融合助力工业场景下人工智能的落地!

一,前言 科技日益发展,总是会诞生出一些新应用和新场景,而这些场景一开始可能并没有对应的解决方案,这个时候就需要定制化的开发来适应新需求,而硬件的定制开发更为头疼,硬件开发设计到外观设计、结构设计、…