51内核单片机实现CRC-16校验,同样适用于51内核的其他芯片(只要稍微修改一下PIC芯片同样适用)

来源:互联网 发布:iphone6将照片导入mac 编辑:程序博客网 时间:2024/05/20 03:46

#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:gxay2000@126.com

原创粉丝点击