CRC校验码计算,以常用CRC-8为例

这篇具有很好参考价值的文章主要介绍了CRC校验码计算,以常用CRC-8为例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。

CRC校验原理:在要发送的帧后面附加一个数,生成一个新帧发送给接收端。它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里是采用“模2除法”)。模2除法:实际上就是异或。

手动计算步骤:

  1. 预先确定一个发送端和接收端都用来作为除数的多项式G(x)
  2. 看所选定的除数二进制位数(假设为k位),然后在要发送的数据帧(假设为m位)后面加上k-1位“0”,然后以这个加了k-1个“0“的新帧(一共是m+k-1位)以“模2除法”方式除以上面这个除数,所得到的余数(也是二进制的比特串)就是该帧的CRC校验码。但要注意的是,余数的位数一定要是比除数位数只能少一位,哪怕前面位是0,甚至是全为0(附带好整除时)也都不能省略。
  3. 把这个校验码附加在原数据帧(就是m位的帧,注意不是在后面形成的m+k-1位的帧)后面,构建一个新帧发送到接收端,最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数,如果没有余数,则表明该帧在传输过程中没出错,否则出现了差错。

例:
多项式G(x) = x8 + x5 + x3 + x2 + x + 1(对应二进制比特串为:100101111),要发送的二进制序列为1100 0101,求CRC校验码是多少,即计算CRC-8

CRC校验码计算,以常用CRC-8为例
代码计算:

/* 以MSB(高位先发)为例 */
/* 单字节计算 CRC-8 */
unsigned char Cal_CRC8(const unsigned char data)
{
    unsigned char i, crc;
    crc = data;
    /* 数据往左移了8位,需要计算8次 */
    for (i = 8; i > 0; i--) {
        /* 判断最高位是否为1 */
        if(crc & 0x80) {
        /* 最高位为1,不需要异或,往左移一位,然后与0x2f异或 */
        /* 0x12f(多项式:x8 + x5 + x3 + x2 + x + 1,  100101111),最高位不需要异或,直接去掉 */
            crc = (crc << 1) ^ 0x2f;
        } else {
            /* 最高位为0时,不需要异或,整体数据往左移一位 */
            crc = (crc << 1);
        }
    }
    return crc;
}

/* 以MSB(高位先发)为例 */
/* 多字节计算 CRC-8 */ */
unsigned char Crc_CRC8_ground(unsigned char *ptr, unsigned char len)
{
    unsigned char i; 
    unsigned char crc=0x00; /* 计算的初始crc值: 0 - 输入值, 1 - 输入翻转 */ 
 
    while(len--)
    {
        crc ^= *ptr++;  /* 每次先与需要计算的数据异或,计算完指向下一数据 */  
        for (i=8; i>0; --i)   /* 下面这段计算过程与计算一个字节crc一样 */  
        { 
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x2f;
            else
                crc = (crc << 1);
        }
    }
 	//reture (~crc); /* 输出翻转 */
    return (crc); 
}

当数据较多时,每次计算就会比较费时,所以还有一种以空间换时间的查表法,即事先穷举出所有结果,通过输入查表获得对应输出

CRC-8:文章来源地址https://www.toymoban.com/news/detail-413494.html

#include <stdio.h>

/* 本地调用此函数计算出所有 CRC-8 校验码 */
unsigned char Cal_CRC8(const unsigned char data)
{
    unsigned char i, crc;
    crc = data;
    /* 数据往左移了8位,需要计算8次 */
    for (i = 8; i > 0; i--) {
        /* 判断最高位是否为1 */
        if(crc & 0x80) {
        /* 最高位为1,不需要异或,往左移一位,然后与0x2f异或 */
        /* 0x12f(多项式:x8 + x5 + x3 + x2 + x + 1,  100101111),最高位不需要异或,直接去掉 */
            crc = (crc << 1) ^ 0x2f;
        } else {
            /* 最高位为0时,不需要异或,整体数据往左移一位 */
            crc = (crc << 1);
        }
    }
    return crc;
}

int main()
{
	unsigned char j = 0;
	int count = 1;
	for(unsigned int i = 0; i < 256; i++) {
   		j = Cal_CRC8(i);
		if(count %  16) {
            count++;
			printf("0x%x, ", j);
		} else {
            count++;
			printf("0x%x,\n", j);
		}
	}
   return 0;
}
#include <stdio.h>

/* 此数组仅供参考,多项式不同,则数组不同 */
/* 多项式:x8 + x5 + x3 + x2 + x + 1,  100101111 */
unsigned char Crc8_Array[] = {
    0x0, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x57, 0x78, 0x9, 0x26, 0xeb, 0xc4, 0xb5, 0x9a,
    0xae, 0x81, 0xf0, 0xdf, 0x12, 0x3d, 0x4c, 0x63, 0xf9, 0xd6, 0xa7, 0x88, 0x45, 0x6a, 0x1b, 0x34,
    0x73, 0x5c, 0x2d, 0x2, 0xcf, 0xe0, 0x91, 0xbe, 0x24, 0xb, 0x7a, 0x55, 0x98, 0xb7, 0xc6, 0xe9,
    0xdd, 0xf2, 0x83, 0xac, 0x61, 0x4e, 0x3f, 0x10, 0x8a, 0xa5, 0xd4, 0xfb, 0x36, 0x19, 0x68, 0x47,
    0xe6, 0xc9, 0xb8, 0x97, 0x5a, 0x75, 0x4, 0x2b, 0xb1, 0x9e, 0xef, 0xc0, 0xd, 0x22, 0x53, 0x7c,
    0x48, 0x67, 0x16, 0x39, 0xf4, 0xdb, 0xaa, 0x85, 0x1f, 0x30, 0x41, 0x6e, 0xa3, 0x8c, 0xfd, 0xd2,
    0x95, 0xba, 0xcb, 0xe4, 0x29, 0x6, 0x77, 0x58, 0xc2, 0xed, 0x9c, 0xb3, 0x7e, 0x51, 0x20, 0xf,
    0x3b, 0x14, 0x65, 0x4a, 0x87, 0xa8, 0xd9, 0xf6, 0x6c, 0x43, 0x32, 0x1d, 0xd0, 0xff, 0x8e, 0xa1,
    0xe3, 0xcc, 0xbd, 0x92, 0x5f, 0x70, 0x1, 0x2e, 0xb4, 0x9b, 0xea, 0xc5, 0x8, 0x27, 0x56, 0x79,
    0x4d, 0x62, 0x13, 0x3c, 0xf1, 0xde, 0xaf, 0x80, 0x1a, 0x35, 0x44, 0x6b, 0xa6, 0x89, 0xf8, 0xd7,
    0x90, 0xbf, 0xce, 0xe1, 0x2c, 0x3, 0x72, 0x5d, 0xc7, 0xe8, 0x99, 0xb6, 0x7b, 0x54, 0x25, 0xa,
    0x3e, 0x11, 0x60, 0x4f, 0x82, 0xad, 0xdc, 0xf3, 0x69, 0x46, 0x37, 0x18, 0xd5, 0xfa, 0x8b, 0xa4,
    0x5, 0x2a, 0x5b, 0x74, 0xb9, 0x96, 0xe7, 0xc8, 0x52, 0x7d, 0xc, 0x23, 0xee, 0xc1, 0xb0, 0x9f,
    0xab, 0x84, 0xf5, 0xda, 0x17, 0x38, 0x49, 0x66, 0xfc, 0xd3, 0xa2, 0x8d, 0x40, 0x6f, 0x1e, 0x31,
    0x76, 0x59, 0x28, 0x7, 0xca, 0xe5, 0x94, 0xbb, 0x21, 0xe, 0x7f, 0x50, 0x9d, 0xb2, 0xc3, 0xec,
    0xd8, 0xf7, 0x86, 0xa9, 0x64, 0x4b, 0x3a, 0x15, 0x8f, 0xa0, 0xd1, 0xfe, 0x33, 0x1c, 0x6d, 0x42,
};

unsigned char Cal_Crc_LookupTable(unsigned char *ptr, unsigned char len) 
{
    unsigned char  crc = 0x00;
 
    while (len--)
    {
        crc = Crc8_Array[crc ^ *ptr++];
    }
    return (crc);
}

int main()
{
	unsigned char crc, data = 0xc5;
	crc = Crc8_Array[data];
    printf("单字节查表:0x%x \n", crc);
	crc = Cal_Crc_LookupTable(&data, sizeof(data));
    printf("多字节查表:0x%x", crc);
   return 0;
}

到了这里,关于CRC校验码计算,以常用CRC-8为例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】CRC(循环冗余校验)

    (1)CRC(Cyclic Redundancy Check),循环冗余校验 (2) 什么是校验,为什么需要校验:数据传输,数据存储过程中需要使用到的 (3)什么是 冗余:表示比实际上要传输的数据还要多 (4)校验实现的关键: 冗余少、运算少、识错纠错能力强 (有些算法只能识别错误但是无法纠错) (1)(

    2024年02月03日
    浏览(40)
  • JAVA获取CRC(即循环冗余校验)

    前言:网上查了很多,CRC计算时,除数长度太长无法计算,所以写此文章。希望大家喜欢!     CRC(Cyclic Redundancy Check),即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数 校核码 的快速算法。      CRC校验本质上是选取一个合适的 除数 ,要进行校

    2024年02月06日
    浏览(30)
  • 从原理到代码理解CRC循环冗余校验

    概述:本文详细介绍了CRC循环冗余计算的数学原理,算法中使用的参数说明,并以Modbus协议中的CRC-16算法为例,进行手算验证,同时提供LabVIEW和C语言的直接计算CRC-16 值的代码以及C的查表计算CRC-16代码和代码原理的说明。 初次接触CRC校验是因为项目需要上位机软件来记录P

    2024年02月04日
    浏览(31)
  • CRC循环冗余校验 (Cyclic Redundancy Check) 原理/电路实现/Verilog实现

    目录 1 什么是CRC循环冗余校验? 2 CRC校验的原理 2.1 多项式表示 2.2 模二 多项式除法 2.3 传输端  2.4 接收端 3 CRC码的产生 3.1 产生CRC码步骤 3.2 Verilog实现 4 电路实现原理—线性反馈移位寄存器 4.1 循环移位寄存器结构 4.2 最大长度移位寄存器  4.3 多项式除法电路(线性反馈移位

    2024年02月04日
    浏览(28)
  • CRC冗余校验的原理和FPGA实现思路

    CRC校验码,顾名思义是用于 校验 的。它可以用于检测数据传输过程中是否出现错误(某些位,或某几位,或者某块区域位错误),反正 可以知道数据出错了,但是不能纠错 。 CRC校验,本质上是模2除法求余。将发送信息 M 当做被除数,发送方和接收方共同约定一个除数 G

    2024年02月08日
    浏览(50)
  • 题解校验码—CRC循环校验码与海明校验码

    一个编码系统的码距是 任意两个码字 的最小距离。 例如个编码系统采用三位长度的二进制编码,若该系统有四种编码分别为:000,011,100,111,此编码系统中000与111的码距为3;011与000的码距为2;011与111的码距为1,则该编码系统的码距为1。 码距计算方法:两个编码按位异

    2024年02月04日
    浏览(32)
  • 计算机网络----CRC冗余码的运算

    冗余码是用于在数据链路层的通信链路和传输数据过程中可能会出错的一种检错编码方法(检错码)。 原理:发送发把数据划分为组,设每组 K 个比特,在其后添加供差错检验用的 n 位冗余码,( K+n )比特一起发送。 过程: 注意: 模二除法运算的过程相当于 异或 。 因为

    2024年02月12日
    浏览(39)
  • 解决灵科路由循环冗余校验错误排除操作指南

    本文为大家介绍的是由于路由器循环冗余校验错误,所造成POS故障的解决办法,循环冗余校验,其特点是:检错能力极强,开销小,易于用编码器及检测电路实现,从其检错能力来看,它所不能发现的错误的几率非常低。 一、组网环境 在灵科路由器的组网环境中,在个点使用

    2024年02月05日
    浏览(35)
  • 16位CRC校验码计算,485MODBUS计算

    CRC计算方法是: 1、 加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器。 2、 把第一个8位二进制数据(即通讯信息帧的第一个字节)与16位的CRC寄存器的相异或,异或的结果仍存放于该CRC寄存器中。 3、 把CRC寄存器的内容右移一位,用0填补最高位,并检测移出位是0还是1。

    2024年02月11日
    浏览(30)
  • CRC32校验算法原理及计算说明

    本文主要介绍如何使用CRC32校验算法计算得出FCS(Frame Check Sequence帧检验序列). 参考: 1、CRC32加密算法原理 2、CRC多项式对应代码 作用:在远距离数据通信中,为确保高效而无差错地传送数据,对数据进行校验即差错控制。 CRC原理实际上就是在一个K位二进制数据序列之后附

    2023年04月22日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包