CRC校验算法

CRC校验算法

   最近搞一个协议,以实现隐蔽通道,其中需要使用CRC校验算法,由于数据位数比较少,最后决定使用位的CRC校验算法。
  该算法主要就是实现一个模二运算,基本原理就是异或,移位。
  模二运算的算法如下(C语言描述):

模二运算
// CrcMOD2函数///////////////////////////////////////////////////////
// 作用:模2运算
// 参数说明;
// m —— 被除数
// p —— 除数
// 返回:余数
unsigned long CrcMOD2(unsigned long m, unsigned long p)
{
    
int m_bits = 0, p_bits = 0, a = 1, bit = 0, flag = 0;
    unsigned 
long m_temp = m, p_temp = p;
    unsigned 
long remainder = 0, andData = 0x00000001;

    unsigned 
long dividend, divisor;

    
// 得到被除数位数
    while (m_temp)
    {
        m_temp 
/= 2;
        
++m_bits;
    }

    
// 得到除数位数
    while (p_temp)
    {
        p_temp 
/= 2;
        
++p_bits;
    }

    
// 如果被除数位数小于除数,则直接返回被除数作为余数
    if (m_bits < p_bits)
        
return m;

    
// 在此开始第一次模2运算
    m_temp = m >> (m_bits - p_bits);    // 被除数右移相应的位数

    dividend 
= m_temp;    // 得到第一次进行运算的被除数
    divisor = p;        // 得到除数

    remainder 
= dividend ^ divisor;        // 得到模2运算的结果作为余数

    m_bits 
-= p_bits;    // 第一次计算完成,减去已经计算过的位数

    
while (m_bits)
    {
        
if (!flag)
        {
            dividend 
= (remainder << 1);    // 上一次得到的余数作为这次被除数的高位
            m_temp = m >> (m_bits - 1);
            bit 
= andData & m_temp;
            dividend 
|= bit;    // 原被除数的某一位作为现在的被除数的最低位
        }
        
else
        {
            dividend 
<<= 1;
            m_temp 
= m >> (m_bits - 1);
            bit 
= andData & m_temp;
            dividend 
|= bit;
        }

        
// 比较除数和被除数的最高位大小
        if ((dividend & (andData << (p_bits - 1))) >=  (divisor & (andData << (p_bits - 1))))
        {
            flag 
= 0;
            remainder 
= dividend ^ divisor;    // 得到模2运算的结果作为余数
        }
        
else
        {
            
// 需要借位
            flag = 1;
        }

        
--m_bits;
    }

    
if (flag)
        remainder 
= dividend;

    
return remainder;
}

  CrcGetCode函数获原始数据和CRC生成多项式,利用模二运算得到新的数据。算法如下:
给数据加上校验码
// CrcGetCode函数///////////////////////////////////////////////////
// 作用:通过原始数据与CRC多项式,得到整个数据的编码
// 参数说明:
// originalData —— 原始数据
// crcPolynomial —— CRC生成多项式
// 返回:原始数据 + 校验码
int CrcGetCode(unsigned long originalData, unsigned long crcPolynomial)
{
    unsigned 
long checkBits = 0, temp = crcPolynomial, m = originalData, fcs;

    
while (temp)
    {
        temp 
/= 2;
        
++checkBits;    // 校验位个数加一
    }
    
-- checkBits;    // 得到校验位个数(比生成多项式少1位)
    m <<= checkBits;            // 得到模二运算的被除数

    
if (checkBits == 0)
        
return m;

    fcs 
= CrcMOD2(m, crcPolynomial);

    m 
|= fcs;    // 加上FCS校验子

    
return m;    // 返回整个编码
}

你可能感兴趣的:(CRC校验算法)