CRC8、CRC16校验原理以及代码实现

 CRC校验算法,说白了,就是把需要校验的数据与多项式进行循环异或(XOR), 
但进行XOR的方式与实际中数据传输时,是高位先传、还是低位先传有关。对于数据 
高位先传的方式,XOR从数据的高位开始,我们就叫它顺序异或吧;对于数据低位先 
传的方式,XOR从数据的低位开始,我们就叫它反序异或吧。两种不同的异或方式, 
即使对应相同的多项式,计算出来的结果也是不一样的。 
下面以顺序异或的例子说明一些计算的过程: 
使用多项式:x8+x5+x4+1(二进制为:100110001) 
计算一个字节:0x11(二进制为:00010001) 
计算步骤: 
A、 因为采用顺序异或,所以需要计算的数据左移8位, 
移位后数据为:0001 0001 0000 000 
B、 先进行高9bit异或(多项式为9bit),0001 0001 0000 0000,因为高9bit的 
最高bit为0,不需要进行异或,同理,接下来的两bit也是0,也不需要进行进行异或。 
这样处理后数据为:1 0001 0000 0000; 
C、 接下来最高位为1,需要进行异或操作了 
CRC8、CRC16校验原理以及代码实现_第1张图片
从上面的计算过程可以看到,多项式最高位为1,遇到需要异或数据最高位为1时, 
才进行异或计算,并且异或后,最高位就为0了,最高位为0,下次也不需要异或了, 
这样需要采用代码计算的方式,就可以把最高位去掉,不需要异或,最后结果也是一样的。

/***************************************

*@DESCRIPTION: --CRC8计算
*
*@Input: --*pdat:待计算CRC8的数据
*   len:待计算CRC8数据的长度
*
*@Return: --无
****************************************/
void Check_CalaCRC8(unsigned char *pdat, unsigned char len)
{
  unsigned int i;
  unsigned char j;
  unsigned char crc = 0x00;
  for (i=0; i  {
    crc ^= ((*pdat++) & 0xFF);
    for (j=8; j>0; j--)
    {
      if (crc & 0x80)
      {
        crc <<= 1;
        crc ^= 0x31;
      }
      else
      { 
        crc <<= 1;
      }
    }
  }
  
  *pdat = crc & 0xFF;

}

*@DESCRIPTION: --CRC8计算
*
*@Input: --*pdat:待校验
*   len:待计算CRC8数据的长度
*
*@Return: --无
****************************************/
void Check_checkCRC8(unsigned char *pdat, unsigned char len)
{
  unsigned int i;
  unsigned char j,sum;
  unsigned char crc = 0x00;
  for (i=0; i  {
    crc ^= ((*pdat++) & 0xFF);
    for (j=8; j>0; j--)
    {
      if (crc & 0x80)
      {
        crc <<= 1;
        crc ^= 0x31;
      }
      else
      { 
        crc <<= 1;
      }
    }
  }
  sum = *pdat;
 
  if (sum == crc) return true;
  return false;

}



//CRC16计算
/***************************************
*@DESCRIPTION: --CRC16计算
*
*@Input: --*pdat:待计算CRC16的数据
*  len:待计算CRC16数据的长度
*
*@Return: --无
****************************************/
void Check_CalaCRC16(unsigned char *pdat, unsigned char len)
{
  unsigned int i;
  unsigned char j;
  unsigned int crc = 0xFFFF;
  for (i=0; i  {
    crc ^= ((*pdat++) & 0x00FF);
    for (j=0; j<8; j++)
    {
      if (crc & 0x0001)
      {
        crc >>= 1;
        crc ^= 0xA001;
      }
      else
      { 
        crc >>= 1;
      }
    }
  }
  
  *pdat++ = crc & 0xFF;
  *pdat = crc>>8;
}



//CRC16校验
/***************************************
*@DESCRIPTION: --CRC16计算是否通过
*
*@Input: --*pdat:待计算CRC16的数据
* len:待计算CRC16数据的长度
*
*@Return: --bool:通过返回true,否则返回false
****************************************/
bool Check_CheckCRC16(unsigned char *pdat, unsigned char len)
{
  unsigned int i,sum;
  unsigned char j;
  unsigned int crc = 0xFFFF;
  for (i=0; i  {
    crc ^= ((*pdat++) & 0x00FF);
    for (j=0; j<8; j++)
    {
      if (crc & 0x0001)
      {
        crc >>= 1;
        crc ^= 0xA001;
      }
      else
      { 
        crc >>= 1;
      }
    }
  }
  
  sum = *pdat++;
  sum += (*pdat) << 8;
  if (sum == crc) return true;


  return false;
}

你可能感兴趣的:(单片机)