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*…

RunMe_Aobut TC103848_UEFIShellFactoryDiagnostics.nsh

:: ***************************************************************************************************************************************************************** :: 20240617 :: 该脚本可以用于BIOS Case TC103848测试,功能包括&#xff1a;在EFIShell环境下运行…

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;就没找到一个是…

算法 Hw9

Hw 9 1 Scheduling with profits and deadlines12345 2 Parallel machine1234 1 Scheduling with profits and deadlines 1 决策问题表述&#xff1a; 给定一个利润值 P P P&#xff0c;是否存在一个任务调度方案使得完成所有任务的总利润至少为 P P P 2 在 NP 类中&…

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…

docker入门——镜像命令、容器命令及其他常用命令

镜像命令 dockers images [-a | -q] 查看镜像 -a: 显示所有细腻些 -q: 只显示镜像ID docker search [–filter]搜索命令 –filter字段值 docker pull 镜像名[:tag] 下载镜像不加tag默认下载最新镜像 docker rmi [options] 删除镜像 ​ -f 容器ID [,容器ID&#xff0c;容…

如何在纯内网环境下,将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发布后的首个更新。…

速盾:海外网站cdn加速免费

随着互联网的快速发展和全球化的趋势&#xff0c;海外网站的重要性也日益增加。然而&#xff0c;由于地理位置等各种因素的限制&#xff0c;海外访问海外网站的速度往往较慢&#xff0c;给用户的体验带来了不便。为了解决这个问题&#xff0c;许多网站开始采用CDN加速技术。 C…

HTML 实体字符简介

在网页设计与开发中&#xff0c;HTML 实体字符扮演着重要的角色&#xff0c;它们帮助我们在HTML文档中安全地插入特殊字符&#xff0c;避免浏览器解析时产生错误或意外的布局效果。实体字符通过特定的编码方式来表示&#xff0c;使得浏览器能够正确识别并展示这些特殊字符。下面…

在云服务器上安装配置和调优Zerotier服务器的详细教程

Hey&#xff0c;朋友们&#xff01;今天我要在服务器上部署和调优Zerotier服务器。使用三丰云提供的免费服务器&#xff0c;配置为1核CPU、1G内存、10G硬盘和5M带宽。虽然配置不高&#xff0c;但三丰云的免费云服务器已经足够应付我们今天的项目。&#x1f44d; Zerotier服务器…

阻塞锁和自旋锁的理解

阻塞锁和自旋锁的理解 文章目录 阻塞锁和自旋锁的理解阻塞锁自旋锁阻塞锁自旋锁各自的优缺点自旋锁阻塞锁 选择自旋锁还是阻塞锁 想象你和你的朋友们一起玩一个游戏&#xff0c;但是每次只能一个人玩。为了决定谁先玩&#xff0c;你们可以用两种方法来排队&#xff1a; 阻塞锁…

小程序-生命周期(2) 应用周期/页面周期

一.应用周期 应用周期指的是小程序&#xff1a;启动->运行->销毁的整个过程。 应用周期伴随一些函数来进行控制&#xff0c;这些函数卸载app.js里面的App方法里。 分别由onLaunch&#xff0c; onShow&#xff0c;onHide依次进行。 onLaunch&#xff1a;初始化的时候运行…

第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个页面。 二、作品演示 三、代…

【玩转google云】实战:如何在GKE上使用Helm安装和配置3节点的RabbitMQ集群

需求 因项目需要需要在Google Kubernetes Engine (GKE) 中使用Helm安装一个3节点的RabbitMQ集群,配置用户名和密码,开通公网访问的Web管理界面,指定namespace为mq,并使用5G的硬盘存储MQ的数据。 前提条件 GKE集群:确保你有一个运行中的GKE集群。Helm工具:确保已安装Hel…