88 lines
2.0 KiB
C++
88 lines
2.0 KiB
C++
|
||
/************************************************************
|
||
* crc16的checksum计算
|
||
* 如果g_ulTable没有初始化,第一次使用的时候将初始化
|
||
***********************************************************/
|
||
|
||
#define CRC16_POLYNOMIAL 0x1021 // CRC_16校验方式的多项式.
|
||
|
||
typedef unsigned char uchar;
|
||
typedef unsigned int uint;
|
||
typedef unsigned long ulong;
|
||
static ulong g_ulTable[256];
|
||
|
||
static bool has_inited = false;
|
||
#include "_osdef.h"
|
||
|
||
// CRC_16方式校验的初始化函数, 计算CRC_16余数表.
|
||
void CRC16Init(void)
|
||
{
|
||
if (has_inited) return;
|
||
uint nRemainder;
|
||
int n, m;
|
||
ulong *pulTable = g_ulTable;
|
||
|
||
for(n = 0; n < 256; n ++)
|
||
{
|
||
nRemainder = (uint)n << 8;
|
||
for(m = 8; m > 0; m --)
|
||
{
|
||
if(nRemainder & 0x8000)
|
||
{
|
||
nRemainder = (nRemainder << 1) ^ CRC16_POLYNOMIAL;
|
||
}
|
||
else
|
||
{
|
||
nRemainder = (nRemainder << 1);
|
||
}
|
||
}
|
||
*(pulTable + n) = nRemainder;
|
||
}
|
||
has_inited =true;
|
||
}
|
||
|
||
|
||
|
||
// 反转数据的比特位, 反转后MSB为1.
|
||
// 反转前: 1110100011101110 0010100111100000
|
||
// 反转后: 1111001010001110 1110001011100000
|
||
unsigned int CRCBitReflect(ulong ulData, int nBits)
|
||
{
|
||
ulong ulResult = 0x00000000L;
|
||
int n;
|
||
for(n = 0; n < nBits; n ++)
|
||
{
|
||
if(ulData & 0x00000001L)
|
||
{
|
||
ulResult |= (ulong)(1L << ((nBits - 1) - n));
|
||
}
|
||
ulData = (ulData >> 1);
|
||
}
|
||
return(ulResult);
|
||
}
|
||
|
||
// 以CRC_16方式计算一个数据块的CRC值.
|
||
// pucData - 待校验的数据块指针.
|
||
// nBytes - 数据块大小, 单位是字节.
|
||
// 返回值是无符号的长整型, 其中低16位有效.
|
||
unsigned int CRC16Calc( unsigned char *pucData, size_t nBytes)
|
||
{
|
||
uint nRemainder, nRet;
|
||
|
||
uchar index;
|
||
if (has_inited ==false)
|
||
{
|
||
CRC16Init(); //如果没有初始化就初始化以下
|
||
}
|
||
ulong *pulTable = g_ulTable;
|
||
nRemainder = 0x0000;
|
||
|
||
for(size_t n = 0; n < nBytes; n ++)
|
||
{
|
||
index = (uchar)CRCBitReflect(*(pucData + n), 8) ^ (nRemainder >> 8);
|
||
nRemainder = (uint)*(pulTable + index) ^ (nRemainder << 8);
|
||
}
|
||
nRet = (uint)CRCBitReflect(nRemainder, 16) ^ 0x0000;
|
||
return(nRet);
|
||
}
|