CRC校验算法

一、什么是CRC校验算法 最近在学网络时在以太网的数据帧的末尾有一个叫CRC校验码的东西,遂不解。于是便一起学习一下,什么是CRC校验码。 CRC就是循环冗余校验码(Cyclic Redundancy Check),是数据通信领域常见的差错校验码,特征是信息字段和校验字段的长度可以任意的选定。 循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,
摘要由CSDN通过智能技术生成

一、什么是CRC校验算法
最近在学网络时在以太网的数据帧的末尾有一个叫CRC校验码的东西,遂不解。于是便一起学习一下,什么是CRC校验码。
CRC就是循环冗余校验码(Cyclic Redundancy Check),是数据通信领域常见的差错校验码,特征是信息字段和校验字段的长度可以任意的选定。

循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接受设备也执行类似的算法来保证数据传输的正确性和完整性。
二、CRC校验算法的算法的原理
CRC校验算法的原理就是:原始帧数据发送之前,在n个bit位的原始数据后面加上通过特定运算得到的K位校验序列,组成新的帧来发送给接收端。接收端会根据原始数据后的校验序列再次进行特定的运算,若正确则接受,若结果错误则丢弃。
这里写图片描述
把上面的K位校验码序列就称为:FCS
CRC校验算法原理的示图如下:
这里写图片描述
我们把特定的运算就称为异或运算。
这样看来CRC校验算法也就是把原始数据通过异或运算得到FCS,接收端根据原始数据再次运算如果相等那么就接收。那么CRC算法的核心就是如何得到FCS。

假设要发送的数据是M,M里面有K个数据,现在要计算冗余码。冗余码的计算方法如下:
1、用二进制模2运算来进行2^n*M也就是M左移了n位,也即是在M的后面加上了n个0,现在M的长度就是K+n
2、用M去除收发双方事先商定的长度为n+1的除数p,得到余数是R
3、这个R就是FCS(帧检验序列),将这个FCS序列加到M后面发出去就行了。

最后接收端对数据进行CRC校验,若余数为R就表示这个帧没有错,就接受。若R不为0表示这个帧出错就丢弃。
一般在数据传输之前,发送端与接收端会相互约定好一个除数(也是一个二进制序列,用来进行模2算法)。这个除数就是生成多项式。这个多项式的最高位和最低位必须为1。
常见的生成多项式为:
CRC8=X8+X5+X4+1(100110001)
CRC-CCITT=X16+X12+X5+1(1001000000100001)
CRC16=X16+X15+X5+1(11000000000100001)
CRC12=X12+X11+X3+X2+1(1100000001101)
CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1
(100000100110000010001110110011111)
给个栗子吧:
M= 101001,p = 1101,n = 3
M是要发送的数据,p是除数,n是在M后面差错检测的n位冗余码
发送端:
M=(2^n*M),所以M=101001000
用M除以p:
这里写图片描述
得到的余数是FCS,将其加到M的后面就是要发送的帧
M = 101001000 + FCS = 101001001

接收端:
接收到的每一帧都要进行差错检验,假设收到的101001001,p=1101,具体如下:
这里写图片描述
我们可以看到最后的余数R=0,没有出错,所以信息是被接收的。
三、CRC算法的编程实现
下面我们通过一个栗子来说明是如何实现CRC校验的,生成多项式为:100110001(简记0x31),也就是CRC-8
计算步骤如下:
(1) 将CRC寄存器(8-bits,比生成多项式少1bit)赋初值0
(2) 在待传输信息流后面加入8个0
(3) While (数据未处理完)
(4) Begin
(5) If (CRC寄存器首位是1)
(6) reg = reg XOR 0x31
(7) CRC寄存器左移一位,读入一个新的数据于CRC寄存器的0 bit的位置。
(8) End
(9) CRC寄存器就是我们所要求的余数。
程序实现的示图:
这里写图片描述
代码展示:(代码来自参考文章的链接里面)
代码是C++实现了CRC8、CRC16和CRC32,代码参考如下:

#ifndef CRCCOMPUTE_H  
#define CRCCOMPUTE_H  

#include <stdint.h>  

template <typename TYPE> class CRC  
{  
public:  
    CRC();  
    CRC(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value);  
    void build(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value);  
    /** 
     * Compute the CRC checksum of a binary message block. 
     * @para message, 用来计算的数据 
     * @para nBytes, 数据的长度 
     */  
    TYPE crcCompute(char * message, unsigned int nBytes);  
    TYPE crcCompute(char * message, unsigned int nBytes, bool reinit);  
protected:  
    TYPE m_polynomial;  
    TYPE m_initial_remainder;  
    TYPE m_final_xor_value;  
    TYPE m_remainder;  
    TYPE crcTable[256];  
    int m_width;  
    int m_topbit;  
    /** 
     * Initialize the CRC lookup table. 
     * This table is used by crcCompute() to make CRC computation faster. 
     */  
    void crcInit(void);  
};  

template <typename TYPE>  
CRC<TYPE>::CRC()  
{  
    m_width = 8 * sizeof(TYPE);  
    m_topbit = 1 << (m_width - 1);  
}  

template <typename TYPE>  
CRC<TYPE>::CRC(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value)  
{  
    m_width = 8 * sizeof(TYPE);  
    m_topbit = 1 << (m_width - 1);  
    m_polynomial = polynomial;  
    m_initial_remainder = init_remainder;  
    m_final_xor_value = final_xor_value;  

    crcInit();  
}  

template <typename TYPE>  
void CRC<TYPE>::build(TYPE polynomial, TYP
  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值