51內核單片機實現CRC-16校驗,同樣適用於51內核的其他芯片(只要稍微修改一下PIC芯片同樣適用)

#include "reg52.h"

#define uint8  unsigned char
#define uint16 unsigned int

unsigned char str[]={0x28,0x6D,0x00,0x85,0x00,0x00,0x00,0xCF};

uint16 CRC_16_UP_Bit(uint8 * dat, uint8 len, uint16 oldcrc);
uint16 CRC_16_UP_NiByte(uint8 * dat, uint8 len, uint16 oldcrc);
uint16 CRC_16_UP_Byte(uint8 * dat, uint8 len, uint16 oldcrc);
/*CRC的初始值爲0x00,多項式爲0xff00,高位在先 */

/*方法一 */
//---------------------------------------
// 功能:逐位計算CRC16(UP_左移正序)
// 輸入:
//      uint8 * dat:要計算CRC的數據指針
//      uint8 len  :數據長度
//      uint16 oldcrc:CRC初始值
// 輸出:生成的新CRC值
//---------------------------------------
uint16 CRC_16_UP_Bit(uint8 * dat, uint8 len, uint16 oldcrc)
{
   uint8 idata i,j;
   uint16 idata x,crc = oldcrc;
   for(i = 0;i < len;i ++)
   {
       crc = crc ^ (dat[i] << 8);
       for (j = 8;j > 0;j --)
       {
           x = crc & 0x8000;
           crc <<= 1;
           if (x != 0)crc ^= 0xFF00;
       }
   }
   return crc;
}

/*方法二 */
//---------------------------------------
// 半字節CRC16(UP_左移正序) 0xFF00 餘式表
//---------------------------------------
uint16 code CRC_16_UP_NiByte_Tab[ 16 ] = {
0x0000 , 0xFF00 , 0x0100 , 0xFE00 ,
0x0200 , 0xFD00 , 0x0300 , 0xFC00 ,
0x0400 , 0xFB00 , 0x0500 , 0xFA00 ,
0x0600 , 0xF900 , 0x0700 , 0xF800
};

//---------------------------------------
// 功能:半字節查表計算CRC16(UP_左移正序)
// 輸入:
//      uint8 * dat:要計算CRC的數據指針
//      uint8 len  :數據長度
//      uint16 oldcrc:CRC初始值
// 輸出:生成的新CRC值
//---------------------------------------
uint16 CRC_16_UP_NiByte(uint8 * dat, uint8 len, uint16 oldcrc)
{
   uint8 idata i,temp;
   uint16 idata crc = oldcrc;
   for(i = 0;i < len;i ++)
   {
       temp = ((uint8)(crc >> 12)) ^ (dat[i] >> 4);
       crc <<= 4;
       crc ^= CRC_16_UP_NiByte_Tab[temp];
       temp = ((uint8)(crc >> 12)) ^ (dat[i] & 0x0F);
       crc <<= 4;
       crc ^= CRC_16_UP_NiByte_Tab[temp];
   }
   return crc;
}

/*方法三 */
//---------------------------------------
// 單字節CRC16(UP_左移正序) 0xFF00 餘式表
//---------------------------------------
uint16 code CRC_16_UP_ByteTab[ 256 ] = {
0x0000 , 0xFF00 , 0x0100 , 0xFE00 , 0x0200 , 0xFD00 , 0x0300 , 0xFC00 ,
0x0400 , 0xFB00 , 0x0500 , 0xFA00 , 0x0600 , 0xF900 , 0x0700 , 0xF800 ,
0x0800 , 0xF700 , 0x0900 , 0xF600 , 0x0A00 , 0xF500 , 0x0B00 , 0xF400 ,
0x0C00 , 0xF300 , 0x0D00 , 0xF200 , 0x0E00 , 0xF100 , 0x0F00 , 0xF000 ,
0x1000 , 0xEF00 , 0x1100 , 0xEE00 , 0x1200 , 0xED00 , 0x1300 , 0xEC00 ,
0x1400 , 0xEB00 , 0x1500 , 0xEA00 , 0x1600 , 0xE900 , 0x1700 , 0xE800 ,
0x1800 , 0xE700 , 0x1900 , 0xE600 , 0x1A00 , 0xE500 , 0x1B00 , 0xE400 ,
0x1C00 , 0xE300 , 0x1D00 , 0xE200 , 0x1E00 , 0xE100 , 0x1F00 , 0xE000 ,
0x2000 , 0xDF00 , 0x2100 , 0xDE00 , 0x2200 , 0xDD00 , 0x2300 , 0xDC00 ,
0x2400 , 0xDB00 , 0x2500 , 0xDA00 , 0x2600 , 0xD900 , 0x2700 , 0xD800 ,
0x2800 , 0xD700 , 0x2900 , 0xD600 , 0x2A00 , 0xD500 , 0x2B00 , 0xD400 ,
0x2C00 , 0xD300 , 0x2D00 , 0xD200 , 0x2E00 , 0xD100 , 0x2F00 , 0xD000 ,
0x3000 , 0xCF00 , 0x3100 , 0xCE00 , 0x3200 , 0xCD00 , 0x3300 , 0xCC00 ,
0x3400 , 0xCB00 , 0x3500 , 0xCA00 , 0x3600 , 0xC900 , 0x3700 , 0xC800 ,
0x3800 , 0xC700 , 0x3900 , 0xC600 , 0x3A00 , 0xC500 , 0x3B00 , 0xC400 ,
0x3C00 , 0xC300 , 0x3D00 , 0xC200 , 0x3E00 , 0xC100 , 0x3F00 , 0xC000 ,
0x4000 , 0xBF00 , 0x4100 , 0xBE00 , 0x4200 , 0xBD00 , 0x4300 , 0xBC00 ,
0x4400 , 0xBB00 , 0x4500 , 0xBA00 , 0x4600 , 0xB900 , 0x4700 , 0xB800 ,
0x4800 , 0xB700 , 0x4900 , 0xB600 , 0x4A00 , 0xB500 , 0x4B00 , 0xB400 ,
0x4C00 , 0xB300 , 0x4D00 , 0xB200 , 0x4E00 , 0xB100 , 0x4F00 , 0xB000 ,
0x5000 , 0xAF00 , 0x5100 , 0xAE00 , 0x5200 , 0xAD00 , 0x5300 , 0xAC00 ,
0x5400 , 0xAB00 , 0x5500 , 0xAA00 , 0x5600 , 0xA900 , 0x5700 , 0xA800 ,
0x5800 , 0xA700 , 0x5900 , 0xA600 , 0x5A00 , 0xA500 , 0x5B00 , 0xA400 ,
0x5C00 , 0xA300 , 0x5D00 , 0xA200 , 0x5E00 , 0xA100 , 0x5F00 , 0xA000 ,
0x6000 , 0x9F00 , 0x6100 , 0x9E00 , 0x6200 , 0x9D00 , 0x6300 , 0x9C00 ,
0x6400 , 0x9B00 , 0x6500 , 0x9A00 , 0x6600 , 0x9900 , 0x6700 , 0x9800 ,
0x6800 , 0x9700 , 0x6900 , 0x9600 , 0x6A00 , 0x9500 , 0x6B00 , 0x9400 ,
0x6C00 , 0x9300 , 0x6D00 , 0x9200 , 0x6E00 , 0x9100 , 0x6F00 , 0x9000 ,
0x7000 , 0x8F00 , 0x7100 , 0x8E00 , 0x7200 , 0x8D00 , 0x7300 , 0x8C00 ,
0x7400 , 0x8B00 , 0x7500 , 0x8A00 , 0x7600 , 0x8900 , 0x7700 , 0x8800 ,
0x7800 , 0x8700 , 0x7900 , 0x8600 , 0x7A00 , 0x8500 , 0x7B00 , 0x8400 ,
0x7C00 , 0x8300 , 0x7D00 , 0x8200 , 0x7E00 , 0x8100 , 0x7F00 , 0x8000
};

//---------------------------------------
// 功能:單字節查表計算CRC16(UP_左移正序)
// 輸入:
//      uint8 * dat:要計算CRC的數據指針
//      uint8 len  :數據長度
//      uint16 oldcrc:CRC初始值
// 輸出:生成的新CRC值
//---------------------------------------
uint16 CRC_16_UP_Byte(uint8 * dat, uint8 len, uint16 oldcrc)
{
   uint8 idata i,temp;
   uint16 idata crc = oldcrc;
   for(i = 0;i < len;i ++)
   {
       temp=(uint8)(crc >> 8) ^ dat[i];
       crc <<= 8;
       crc ^= CRC_16_UP_ByteTab[temp];
   }
   return crc;
}

void main (void)
{
  uint8 *d;
  uint16 crctest=0;
  d=&str[0];
  crctest=CRC_16_UP_Bit(d, 7, 0x0000);
  crctest=0;
  crctest=CRC_16_UP_NiByte(d, 7, 0x0000);
  crctest=0;
  crctest=CRC_16_UP_Byte(d, 7, 0x0000);

  while(1)
  {
  ;
  }
}

 

上面給出了3種方法,可以根據自己所使用的單片機來選擇不同的方法,

方法一:單片機的運算速度快,ROM比較小的情況下適用;

方法三:單片機的運算速度慢,ROM比較大的情況下適用;

方法二:是前面兩種方法的折中選擇,我比較推薦大家用的;

用Keil uVision3編譯的結果如下:

Program Size: data=32.0 xdata=0 code=1198

"CRC16" - 0 Error(s), 0 Warning(s).

在51內核的芯片上面已經通過驗證,大家可以放心使用,各位有什麼更好的方法可以發E-Mail:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章