#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