2024年4月27日发(作者:)

word格式-可编辑-感谢下载支持

CRC16校验C语言程序源码 (附完整的可执行的C语言代码)

//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的2种

//实现方法进行测试。

方法一:查表法(256长度的校验表)

速度快,准确,但是对于单片机设备存储占用大,且校验表长度大,输入时容易出现错误。

// ---------------- POPULAR POLYNOMIALS ----------------

// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021)

// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005)

#define CRC_16_POLYNOMIALS 0x8005

const BYTE chCRCHTalbe[] = // CRC 高位字节值表

{

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40

};

const BYTE chCRCLTalbe[] = // CRC 低位字节值表

{

0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,

0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,

0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,

0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,

0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,

0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,

0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,

word格式-可编辑-感谢下载支持

0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,

0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,

0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,

0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,

0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,

0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,

0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,

0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,

0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,

0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,

0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,

0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,

0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,

0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,

0x41, 0x81, 0x80, 0x40

};

WORD CRC16_1(BYTE* pchMsg, WORD wDataLen)

{

BYTE chCRCHi = 0xFF; // 高CRC字节初始化

BYTE chCRCLo = 0xFF; // 低CRC字节初始化

WORD wIndex; // CRC循环中的索引

while (wDataLen--)

{

// 计算CRC

wIndex = chCRCLo ^ *pchMsg++ ;

chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];

chCRCHi = chCRCLTalbe[wIndex] ;

}

return ((chCRCHi << 8) | chCRCLo) ;

}

方法一:列表法(简单表)

const WORD wCRCTalbeAbs[] =

{

0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401,

0x5000, 0x9C01, 0x8801, 0x4400,

};

WORD CRC16_2(BYTE* pchMsg, WORD wDataLen)

{

WORD wCRC = 0xFFFF;

word格式-可编辑-感谢下载支持

WORD i;

BYTE chChar;

for (i = 0; i < wDataLen; i++)

{

chChar = *pchMsg++;

wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);

wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);

}

return wCRC;

}

方法二:定义法

根据CRC16/MODBUS原理直接计算,算法简单但对单片机计算压力大。

WORD CRC16_3(BYTE* pchMsg, WORD wDataLen)

{

BYTE i, chChar;

WORD wCRC = 0xFFFF;

while (wDataLen--)

{

chChar = *pchMsg++;

chChar = ByteInvert(chChar);

wCRC ^= (((WORD) chChar) << 8);

for (i = 0; i < 8; i++)

{

if (wCRC & 0x8000)

wCRC = (wCRC << 1) ^

CRC_16_POLYNOMIALS;

else

wCRC <<= 1;

}

}

wCRC = WordInvert(wCRC);

return wCRC;

}

//试验数据:

// 采用Metrowerks CodeWarrior在DSP56F80x平台上,对这3种方法

//进行了性能测试。

// ----------------------------------------------------------------

// 代码大小(字) 额外存储空间(字) 执行时间(周期数)

word格式-可编辑-感谢下载支持

// ----------------------------------------------------------------

// 方法1

32 512 540

// 方法2

57 16 1120

// 方法3

142*

//

0 4598

附一个完整的C语言代码

#include

void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)

{

int i;

unsigned char tmp[4];

tmp[0] = 0;

for(i=0;i< 8;i++)

{

if(srcBuf[0]& (1 << i))

tmp[0]|=1<<(7-i);

}

dBuf[0] = tmp[0];

}

void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)

{

int i;

unsigned short tmp[4];

tmp[0] = 0;

for(i=0;i< 16;i++)

{

if(srcBuf[0]& (1 << i))

tmp[0]|=1<<(15 - i);

}

dBuf[0] = tmp[0];

}

unsigned short CRC16_MODBUS(unsigned char *puchMsg, unsigned int usDataLen)

{

word格式-可编辑-感谢下载支持

unsigned short wCRCin = 0xFFFF;

unsigned short wCPoly = 0x8005;

unsigned char wChar = 0;

int i;

while (usDataLen--)

{

wChar = *(puchMsg++);

InvertUint8(&wChar,&wChar);

wCRCin ^= (wChar << 8);

for(i = 0;i < 8;i++)

{

if(wCRCin & 0x8000)

wCRCin = (wCRCin << 1) ^ wCPoly;

else

wCRCin = wCRCin << 1;

}

}

InvertUint16(&wCRCin,&wCRCin);

return (wCRCin) ;

}

int main()

{

unsigned char puchMsg[10]="";

unsigned short result=CRC16_MODBUS(puchMsg,10); //字符串可直接用%是输入,具

体应用具体实现,但后面的int

型参数对应字符串长度必须正

确。

printf("%X",result);

}