⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crc.c

📁 网站上的算法大都是查512字节表的
💻 C
字号:
/* 一些见于标准的CRC:
	CRC-4      x^4 + x + 1
	CRC-12     X^12 + X^11 + X^3 + X + 1
	CRC-16     X^16 + X^12 + X^2 + 1
	CRC-32	 X^32 + X^26 +X^15 + .... + 1
	...
   CRC 可以由除法电路的主体由一组移位寄存器和模2加法器(异或单元)组成(本例子由16级移位寄存器和3个加法器组成)
   CRC除法电路,完全可以用软件来模拟
   定义一个寄存器组,初始化为全"1"。每输入一个信息位,相当于一个时钟脉冲到来,从高到低依次移位。移位前
   信息位与bit0相加产生临时位,其中bit15移入临时位,bit10、bit3还要加上临时位。当全部信息位输入完成后,
   从寄存器组取出它们的值,这就是CRC码。
*/

typedef union _UNION_CRCREGS
{
	INT16U crcValue;
	struct
	{
		INT16U bit0 : 1;
		INT16U bit1 : 1;
		INT16U bit2 : 1;
		INT16U bit3 : 1;
		INT16U bit4 : 1;
		INT16U bit5 : 1;
		INT16U bit6 : 1;
		INT16U bit7 : 1;
		INT16U bit8 : 1;
		INT16U bit9 : 1;
		INT16U bit10 : 1;
		INT16U bit11 : 1;
		INT16U bit12 : 1;
		INT16U bit13 : 1;
		INT16U bit14 : 1;
		INT16U bit15 : 1;		
	} STRUCT_BITS;
} UNION_CRCREGS;  //  end of define SRUCT_CRCREGS

//
// 定义一个寄存器组
//
UNION_CRCREGS rCRCReg;

//
// InitCRCRegs
// 初始化寄存器组,寄存器组全置 1
//
void
InitCRCRegs(
	void
)
{
	rCRCReg.crcValue = 0xffff;  //  寄存器组全置 1
}

//
// CRCInputOneBit
// CRC 输入1位
//
void
CRCInputOneBit(
	BOOLEAN crcIN
)
{
	BOOLEAN bitTemp;

	bitTemp = rCRCReg.STRUCT_BITS.bit0 ^ crcIN;

	//
	// 中一步一步的移位/异或操作
	//
	rCRCReg.STRUCT_BITS.bit1 = rCRCReg.STRUCT_BITS.bit2;
	rCRCReg.STRUCT_BITS.bit2 = rCRCReg.STRUCT_BITS.bit3;
	rCRCReg.STRUCT_BITS.bit3 = rCRCReg.STRUCT_BITS.bit4 ^ bitTemp;
	rCRCReg.STRUCT_BITS.bit4 = rCRCReg.STRUCT_BITS.bit5;
	rCRCReg.STRUCT_BITS.bit5 = rCRCReg.STRUCT_BITS.bit6;
	rCRCReg.STRUCT_BITS.bit6 = rCRCReg.STRUCT_BITS.bit7;
	rCRCReg.STRUCT_BITS.bit7 = rCRCReg.STRUCT_BITS.bit8;
	rCRCReg.STRUCT_BITS.bit8 = rCRCReg.STRUCT_BITS.bit9;
	rCRCReg.STRUCT_BITS.bit9 = rCRCReg.STRUCT_BITS.bit10;
	rCRCReg.STRUCT_BITS.bit10 = rCRCReg.STRUCT_BITS.bit11 ^ bitTemp;
	rCRCReg.STRUCT_BITS.bit11 = rCRCReg.STRUCT_BITS.bit12;
	rCRCReg.STRUCT_BITS.bit12 = rCRCReg.STRUCT_BITS.bit13;
	rCRCReg.STRUCT_BITS.bit13 = rCRCReg.STRUCT_BITS.bit14;
	rCRCReg.STRUCT_BITS.bit14 = rCRCReg.STRUCT_BITS.bit15;
	rCRCReg.STRUCT_BITS.bit15 = bitTemp;	
}// end CRCInputOneBit

/*crcInputBit中一步一步的移位/异或操作,可以进行简化:*/
//
// CRCInputOneBit_1
// CRC 输入1位
//
void
CRCInputOneBit_1(
	BOOLEAN crcIN
)
{
	BOOLEAN crcTemp;

	crcTemp = rCRCReg.STRUCT_BITS.bit0 ^ crcIN;
	rCRCReg.crcValue >>= 1;
	if (crcTemp)
	{	
		/* 可以发现0x8408和0x1021(CRC-ITU的简记式)之间的关系。
		由于我们是从低到高输出比特流的,将0x1021左右反转就得到0x8408。
		将生成多项式写成 G(x)=1+X^5+X^12+X^16,是不是更好看一点*/
		rCRCReg.crcValue ^= 0x8408;  /
	}
} // End of CRCInputOneBit_1


//
// GetCRCRegValue
// 输出CRC码(寄存器组的值)
//
INT16U 
GetCRCRegValue(
	void
)
{
	return rCRCReg.crcValue;
} // end of GetCRCRegValue

// ========================================================================================
// 下面是一个典型的PPP帧。最后两个字节称为FCS(Frame Check Sequence),是前面11个字节的CRC。
// FF 03 C0 21 04 03 00 07 0D 03 06 D0 3A
// 我们来计算这个PPP帧的CRC,并验证它。
// ========================================================================================
//
// CaculatCRC
//
INT16U
CaculatCRC(
	void
)
{
	INT8U PPP[13] = 
		{0xff,0x03,0xc0,0x21,0x04,0x03,0x00,0x07,0x0d,0x03,0x06,0xd0,0x3a};
	INT8U i, j;
	
	INT16U crcResult;  // 用于存放CRC计算的结果
	//
	// 以下进行CRC寄存器初始化
	//
	InitCRCRegs ();

	//
	// 逐位输入ppp[i],每个字节低位在先,不包括两个FCS字节
	//
	for (i = 0; i < 11; i ++)
	{
		for (j = 0; j < 8; j ++)
		{
			CRCInputOneBit (ppp[i] >> j) // ?
		}
	}
	//
	// 得到CRC:将寄存器组的值求反
	//
	crcResult = ~ GetCRCRegValue();

	//
	// 填写FCS,先低后高
	//
	ppp[11] = crcResult % 26amp;  // ??? what's 26amp
	ppp[12] = (crcResult >> 8) % 26amp // ???	
}// End of CaculatCRC

//
// CheckCRC16
//
INT16U
ChechCRC16(
	void
)
{
	INT8U i, j;
	INT16U crcResult;
	//
	// 初始化 register
	//
	InitCRCRegs ();
	//
	// 逐位输入,每个字节低位在先,包括两个FCS字节
	//
	for (i = 0; i < 13; i ++)
	{
		for (j = 0; j < 8; j ++)
		{
			CRCInputOneBit (ppp[i] >>j);
		}
	}
	//
	// 得到验证结果
	//
	crcResult = GetCRCRegValue();
	return crcResult;
}// End of CheckCRC16

 // ================================================================================
 // 下面是通用的CRC-ITU查找表以及计算和验证CRC的C语言程序
 // ================================================================================
 #include "crc16tab.h"
 //
 // GetCRC16
 // 计算给定长度数据的16位CRC
 //
INT16U
GetCRC16(
	const INT8U *pData,
	INT16U nLength
)
{
	INT16U FCS = 0Xffff; // FCS 初始化为0xffff

	while (nLength > 0)
	{
		FCS = (FCS >> 8) ^ crc16TAB[(FCS ^ * PData) % 26amp ; 0xff] // ???
		nLength --;
		pData ++;
	}
	return (~ FCS);
}

//
// IsCRC16Good
// 检查给定长度数据的16位CRC是否正确
//
// 正确反回1,错误返回0
//
BOOLEAN
IsCRC16Good(
	INT8U *pData,
	INT16U nLength
)
{
	BOOLEAN bResult;
	INT16U FCS;

	while (nLength > 0)
	{
		FCS = (FCS >> 8) ^ crc16TAB[(FCS ^ *pData) % 26amp; 0xff]; // ???
		nLength --;
		pData ++;
	}
	if (FCS ==0xf0b8)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}// End of IsCRC16Good
//
// ==================================================================================
//
// 注意:因最高位一定为“1”,故略去 
//
const INT16U cnCRC_16 = 0x8005; 
//
// CRC-16 = X16 X15 X2 X0 
//
const INT16U cnCRC_CCITT = 0x1021; 
//
// CRC-CCITT = X16 X12 X5 X0,据说这个 16 位 CRC 多项式比上一个要好 
//
const INT32U cnCRC_32 = 0x04C10DB7; 
//
// CRC-32 = X32 X26 X23 X22 X16 X11 X10 X8 X7 X5 X4 X2 X1 X0 
//
INT32U Table_CRC[256]; // CRC 表 
//
// ==================================================================================
//
// 构造 16 位 CRC 表 
//
void 
BuildTable16(
	INT16U aPoly 
) 
{ 
	INT16U i, j; 
	INT16U nData; 
	INT16U nAccum; 

	for (i = 0; i < 256; i) 
	{ 
		nData = (INT16U)(i << 8); 
		nAccum = 0; 
		for (j = 0; j < 8; j) 
		{ 
			if ((nData ^ nAccum) & 0x8000) 
			nAccum = (nAccum << 1) ^ aPoly; 
			else 
			nAccum <<= 1; 
			nData <<= 1; 
		} 
	Table_CRC[i] = (INT32U)nAccum; 
	} 
} 

// 计算 16 位 CRC 值,CRC-16 或 CRC-CCITT 
INT16U 
CRC_16(
	INT8U * aData, 
	INT32U aSize 
) 
{ 
	INT32U i; 
	INT16U nAccum = 0; 

	BuildTable16(cnCRC_16); // or cnCRC_CCITT 
	for (i = 0; i < aSize; i)
	{
		nAccum = (nAccum << 8) ^ 
				 (INT16U)Table_CRC[(nAccum >> 8) ^ *aData ]; 
	}
	return nAccum; 
} // End of CRC_16

// 构造 32 位 CRC 表 
void 
BuildTable32(
	INT32U aPoly 
) 
{ 
	INT32U i, j; 
	INT32U nData; 
	INT32U nAccum; 

	for (i = 0; i < 256; i) 
	{ 
		nData = (INT32U)(i << 24); 
		nAccum = 0; 
		for (j = 0; j < 8; j) 
		{ 
			if ((nData ^ nAccum) & 0x80000000)
			{
				nAccum = (nAccum << 1) ^ aPoly; 
			}
			else
			{
				nAccum <<= 1; 
			}
			nData <<= 1;
		} 
	Table_CRC[i] = nAccum; 
	} 
}// End of BuildTable32 

//
// 计算 32 位 CRC-32 值 
//
INT32U 
CRC_32(
	INT8U * pData, 
	INT32U aSize 
) 
{ 
	INT32U i; 
	INT32U nAccum = 0; 

	BuildTable32(cnCRC_32); 
	for (i = 0; i < aSize; i) 
	{
		nAccum = (nAccum << 8) ^ 
				 Table_CRC[(nAccum >> 24) ^ * pData]; 
	}
	return nAccum; 
} // End of CRC_32 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -