CRC循环冗余校验

CRC循环冗余校验

循环冗余校验码是一种用在数字网络和存储设备上的差错校验码,可以校验原始数据的偶然差

错。

CRC 计算单元使用固定多项式计算 32 位 CRC 校验码。

1. 硬件CRC

在单片机中,芯片具有专用的CRC计算单元,它是按照32位数据长度进行计算。 它相当于是我们的MCU有个小老弟,专门是干CRC计算的。

主要特征

1.1. 在C代码计算CRC

下面我们在C代码中去使用CRC循环冗余校验码:

  1. 在工程中导入gd32f4xx_crc.c文件
  2. 参考下面的示例代码,对数据进行计算
void example26_crc_test(){// 开启外设时钟rcu_periph_clock_enable(RCU_CRC);// 复位crc_deinit();// 数据重置crc_data_register_reset();// 要发送的数据uint32_t data[] = {0x00000001,0x00000002,0x00000003,0x00000004};// CRC校验码  uint32_t crc_data = crc_block_data_calculate((uint32_t*)data,4);printf("0x%X\r\n",crc_data);
}

1.2. 在线计算CRC

CRC(循环冗余校验)在线计算_ip33.com

1.3. 比对二者结果

通过下图,我们可以看到两端所计算的结果是相同的,说明数据在通讯的过程中,数据是正确的。

如果通讯的过程中,数据传错了,哪怕是错一位,最终计算出来的结果都是不一致的。

请问下图,我错在哪?

2. 软件CRC

在上面的案例中,我们是将数据传输给硬件计算单元去计算,但是芯片默认只支持32位的结果输出。但是在日常开发中,我们使用16位或者8位的情况非常多,所以我们无法直接使用硬件CRC,这个时候,咱们就得使用软件CRC自己来计算。

好的,我来简单地描述一下如何在软件中实现CRC(循环冗余校验)的步骤:

选择多项式生成器: 首先需要确定使用哪种CRC多项式作为生成器。常见的有CRC-16、CRC-32等多种选择,需要根据实际需求选择合适的生成器。

例如在我们硬件CRC,芯片内部默认使用的多项式生成器是 0x4C11DB7

对每个输入数据位执行以下步骤:

a. 取一个字节数据,将字节左移到最高处

b. 将左移之后的数据和初值进行异或处理,将结果作为新初值

c. 处理新初值每一位, 判断最高位是否是1:

  1. 如果是1,则新初值左移1位后和多项式进行异或,将结果设置为新初值
  2. 如果是0,仅左移。

重复步骤3,直到所有输入数据位都处理完毕。

输出结果: 此时出书的就是最终的CRC校验码。

通常,我们进行数据的传输都是使用字节进行传输的,所以在以下的案例中,我们的数据都是按照1字节的方式进行计算

2.1. 32位CRC

uint32_t calculate_crc32(uint8_t *data, uint32_t length) {uint32_t crc  = 0xFFFFFFFF;uint32_t poly = 0x04C11DB7;  for(int i=0; i< length;i++){// 1. 取出1个字节uint32_t d = data[i];// 2. 将数据进行左移,最高处是32位,传入的数据是8位的,所以左移24crc = crc ^ (d << 24);// 3. 处理新初值每一位for (int j = 0; j < 8; j++) {if (crc & 0x80000000) { // 若最高位是1,则左移1位与多项式进行异或crc = (crc << 1) ^ poly;} else {crc = crc << 1;   //若最高位不是1, 则右移一位}}}return crc;
}

void example27_crc_soft_test(){uint8_t data[] = {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04};// CRC校验码  uint32_t crc_data = calculate_crc32(data,16);printf("0x%X\r\n",crc_data);
}

2.2. 16位CRC

uint32_t calculate_crc16(uint8_t *data, uint32_t length) {uint32_t crc  = 0xFFFF;uint32_t poly = 0x8005;  for(int i=0; i< length;i++){// 1. 取出1个字节uint32_t d = data[i];// 2. 将数据进行左移,最高处是16位,传入的数据是8位的,所以左移8crc = crc ^ (d << 8);// 3. 处理新初值每一位for (int j = 0; j < 8; j++) {if (crc & 0x8000) { // 若最高位是1,则左移1位与多项式进行异或crc = (crc << 1) ^ poly;} else {crc = crc << 1;   //若最高位不是1, 则右移一位}}}return crc;
}

测试代码

  uint8_t data16[] = {0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04};uint16_t crc_data = calculate_crc16(data16,8);printf("0x%X\r\n",crc_data);

执行代码,查看代码运行结果是否和网页计算一致

2.3. 8位CRC

uint32_t calculate_crc8(uint8_t *data, uint32_t length) {uint32_t crc  = 0xFF;uint32_t poly = 0x80;  for(int i=0; i< length;i++){// 1. 取出1个字节uint8_t d = data[i];// 2. 将数据进行左移,最高处是8位,传入的数据是8位的,所以左移0crc = crc ^ (d << 0);// 3. 处理新初值每一位for (int j = 0; j < 8; j++) {if (crc & 0x80) { // 若最高位是1,则左移1位与多项式进行异或crc = (crc << 1) ^ poly;} else {crc = crc << 1;   //若最高位不是1, 则右移一位}}}return crc;
}
uint8_t data8[] = {0x01,0x02,0x03,0x04};
uint8_t crc_data8 = calculate_crc8(data8,4);
printf("0x%X\r\n",crc_data8);

在网页中查看执行结果,比对与程序执行输出的结果是否一致

3. 模拟数据传输

在该案例中,我们使用单片机作为发送端,使用python客户端作为接收端。

  1. 在单片机端, 我们先对数据计算一个CRC校验码
  2. 在接收端,我们重新对数据计算一个CRC校验码
  3. 比对收到的校验码和自己计算出来的校验码
    1. 若相同,则数据校验成功
    2. 若不同,则数据校验失败

3.1. 在python中实现CRC8

按照前面的步骤,我们将CRC算法在python中实现一遍


def crc8(data, init_crc):poly = 0x80for d in data:init_crc = init_crc^d # 1.for i in range(8):if init_crc&0x80:init_crc = (init_crc<<1)^polyelse:init_crc = init_crc << 1return init_crc&0xff  # 这里的0xff只是为了去取出8位数据

3.2. 单片发出数据

在单片机中,我们循环的去发送数据


  while(1){// 假设我们要发送的数据是前4个字节uint8_t data8[5] = {0x01,0x02,0x03,0x04,0};// 计算数据的CRC校验码uint8_t crc_data8 = calculate_crc8(data8,4);// 将CRC校验码拼接到要发送数据的末尾data8[4] = crc_data8;usart0_dma_send_data(data8,5);delay_1ms(2000);}

3.3. python接收数据

在python客户端中,我们要干如下几件事:

  1. 接收到客户端数据
  2. 将数据转成字节数组
  3. 从字节数组中拆分出数据部分和校验码部分
  4. 使用crc校验算法,对数据部分重新计算校验码
  5. 比对计算出来的校验码和接收到的校验码
    1. 若相同,则校验成功
    2. 若不同,则校验失败,该条数据就是辣鸡
ser = serial.Serial("COM58", 115200, timeout=3000)
print("ser is open:",ser.isOpen())while True:# print(ser)count = ser.in_waiting# 先找到头if count >= 5:data = ser.read(count)print(f"count={count},data={data}");if count == 5:result = struct.unpack('<BBBBB',data )print(f"result={result}")# 将数据部分取出来,计算校验码code = crc8(result[0:4],0xff)print("tx_code=0x{:02X}, rx_code=0x{:02X}".format(result[4],code)) time.sleep(0.001)ser.close()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 48.旋转图像

1.做题要求: 2.从此题我们可以看出规律为第几行要变为倒数第几列&#xff0c;所以我们最好先把二维数组存入一维数组中&#xff0c;然后先从最后一列遍历&#xff0c;把一维数组里的元素&#xff0c;依次等于遍历的元素即可: void rotate(int** matrix, int matrixSize, int*…

Scala函数

文章目录 一、第1关&#xff1a;方法S 三角形 ​实验代码&#xff1a; 二、第2关&#xff1a;Scala函数以及函数调用实验代码&#xff1a; 一、第1关&#xff1a;方法 任务描述 本关任务&#xff1a;根据三角形的三边长 a、b、c&#xff0c;返回三角形的面积。 任意三角形面积…

外网怎么访问内网?

当我们需要在外网环境下访问内网资源时&#xff0c;常常会面临一些困扰。通过使用一些相关的技术与工具&#xff0c;我们可以轻松地实现这一目标。本文将介绍如何通过【天联】组网产品&#xff0c;解决外网访问内网的问题。 【天联】组网是一款由北京金万维科技有限公司自主研…

JAVAFX打包部署真正能用的办法(jdk21,javafx23)IntelliJ IDEA

我之前创建了javafx项目&#xff0c;想打包试试。一试&#xff0c;全是坑&#xff0c;所以记录下来&#xff0c;为有缘人节约时间。直接构建工件是错误的&#xff0c;别尝试了&#xff0c;找不在JDK的。我也花了一天多的时间尝试了网上各种大神的办法&#xff0c;就没找到一个是…

stm32学习-软件I2C读取MPU6050

接线 SDAPB11SCLPB10 I2C 对操作端口的库函数进行封装 void MyI2C_W_SCL(uint8_t BitValue)//写 {GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);Delay_us(10); }void MyI2C_W_SDA(uint8_t BitValue)//写 {GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValu…

Redis 7.x 系列【4】命令手册

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 说明2. 命令手册2.1 Generic2.2 数据类型2.2.1 String2.2.2 Hash2.2.3 List2.2.4 S…

如何在纯内网环境下,将EasyCVR视频汇聚网关通过4G与第三方公网云平台级联?

EasyCVR视频汇聚网关是TSINGSEE青犀软硬一体的一款产品&#xff0c;可提供多协议的接入、音视频采集、处理&#xff0c;能实现海量前端设备的轻量化接入/转码/分发、视频直播、云端录像、云存储、检索回看、智能告警、平台级联等&#xff0c;兼容多种操作系统&#xff0c;轻松扩…

HTTP/2 协议学习

HTTP/2 协议介绍 ​ HTTP/2 &#xff08;原名HTTP/2.0&#xff09;即超文本传输协议 2.0&#xff0c;是下一代HTTP协议。是由互联网工程任务组&#xff08;IETF&#xff09;的Hypertext Transfer Protocol Bis (httpbis)工作小组进行开发。是自1999年http1.1发布后的首个更新。…

第3讲:关于Pixi的Text、Container、Sprite、Graphics组件功能作用

首先这里提供一个公用代码&#xff1a; 下部分各种组件基于这个公用代码直接往下添加代码即可。 import {Application, Text, Container, Sprite, BaseTexture, Texture, Graphics} from pixi.js import ./style.css import testImageUrl from ./images/test.jpg // 指明Appli…

3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)

前端异步编程规范 Promise介绍手写Promise&#xff08;resolve&#xff0c;reject&#xff09;手写Promise&#xff08;then&#xff09;Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类&#xff0c;可以翻…

HTML静态网页成品作业(HTML+CSS)—— 家乡成都介绍网页(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有4个页面。 二、作品演示 三、代…

C语言 | Leetcode C语言题解之第164题最大间距

题目&#xff1a; 题解&#xff1a; int maximumGap(int* nums, int numsSize) {if (numsSize < 2) {return 0;}int maxVal INT_MIN, minVal INT_MAX;for (int i 0; i < numsSize; i) {maxVal fmax(maxVal, nums[i]);minVal fmin(minVal, nums[i]);}int d fmax(1,…

计算机网络:3数据链路层

数据链路层 概述封装成帧和透明传输帧透明传输&#xff08;填充字节或比特&#xff09;差错检测奇偶校验循环冗余校验CRC Cyclic Redundancy Check 可靠传输停止-等待协议回退n帧协议&#xff08;滑动窗口协议&#xff09;选择重传协议 点对点协议PPP共享式以太网网络适配器&am…

React+TS前台项目实战(十一)-- 全局常用组件提示语可复制Link组件封装

文章目录 前言HighLightLink组件1. 功能分析2. 代码详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇讲的这个组件&#xff0c;是一个用于高亮显示文本并添加可选的跳转链接&#xff0c;提示文本&#xff0c;复制文本的 React 组件 HighLightLink组件 1. 功能分析 &#x…

【交易策略】#22-24 残差资金流强度因子

【交易策略】#22-24 残差资金流强度因子

路由控制和策略路由

文章目录 一、路由控制&#xff08;1&#xff09;、前言1.1.1-路由策略 &#xff08;2&#xff09;、正反掩码和通配符1.2.1-通配符 &#xff08;3&#xff09;、ACL1.3.1-ACL步长1.3.2-步长的作用1.3.3-TCP/UDP端口号 实验1:实验2: 二、前缀列表实验1:2.1.1-前缀列表的表达式2…

【图像分割】DSNet: A Novel Way to Use Atrous Convolutions in Semantic Segmentation

DSNet: A Novel Way to Use Atrous Convolutions in Semantic Segmentation 论文链接&#xff1a;http://arxiv.org/abs/2406.03702 代码链接&#xff1a;https://github.com/takaniwa/DSNet 一、摘要 重新审视了现代卷积神经网络&#xff08;CNNs&#xff09;中的atrous卷积…

找工作小项目:day16-重构核心库、使用智能指针(1)

day16-重构核心库、使用智能指针 今天是该项目开源在gthub的最后一天&#xff0c;我这里只是将我自己对于这个项目的理解进行总结&#xff0c;如有错误敬请包含指正&#xff0c;今天会整体理一遍代码&#xff0c;并使用智能指针管理整个项目。 1、common 头文件 定义宏用于…

/usr/bin/ld: 当搜索用于 /lib/i386-linux-gnu/libcuda.so 时跳过不兼容的 -lcuda

/usr/bin/ld: 当搜索用于 /lib/i386-linux-gnu/libcuda.so 时跳过不兼容的 -lcuda ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/023dbdeb215b4b4580f7f54706e32af9.pn当使用unsloth做微调时&#xff0c;发现找不到libcuda&#xff0c;很自然想到需要软链接到最新…

IDEA2023中使用run Dashboard面板?实现批量运行微服务

1、直接点击Add service--->Run Configuration Type---->Spring Boot 2、这样就出现了run Dashboard面板&#xff0c;可同时运行多个工程模块&#xff0c;shift选中所有启动类组命名&#xff08;Group Configurations&#xff09; 3、启动所有的项目