/*前段时间在作项目中用到了CRC循环校验,在网上查了不少资料,可是都很零乱;
本人做了相关整理,并对经常使用的循环冗余校验进行了封装,造成本文件。
在这里感谢网络上提供相关资料的朋友们,关于他们的名字在这里我没法一一列举,再次向他们表示感谢!*/
/*
须要注意的是:即便都是一样位数的crc校验,多项式也能够不一样。即便多项式相同,初值,末值xor,是否反转等设置也能够不一样
因此在通讯的双方须要约定好。
如下的具体crc子类只是我能找到的一些经常使用的crc约定。
哪位兄弟有具体的crc约定,能够告知我进行扩展。
*/
//* 采用了泛型定义基类,基类是一个通用的计算CRC的方法,定义具体的类时只须要设置好CRC设置便可。
//* 原本想用c#写模版代码,但是C#编译器竟然先检查 >> & 计算,说T没法进行这些操做,没法编译经过。
//* 因此改为用c++实现.因此c#仍是只能称为泛型,而c++才能称为模板
//**********************************************************************************************************/
//crc的设置.选用一个crc算法时,子类必须设置这些值
int m_order;//CRC多项式的阶数 1到64
T m_polynom;//CRC多项式
T m_crcinit;//CRC的初值
T m_crcxor;//和最终结果xor的值
int m_refin;//0或者1,表示输入在处理前是否反转
int m_refout;//0或者1,表示输出结果是否反转
int m_direct;//0或者1,1表示直接使用m_crcinit
CRC的原理,俺这里就不说了。你们能够参考网上的不少资料。
下面是源代码:
#pragma once
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Diagnostics;
#pragma warning(disable:4333)
namespace Hob{namespace Toolbox{namespace Classes
{
/// <summary>
/// CRC基类,抽象类,模版类.注:T只能是long,int,byte...等
/// </summary>
template<typename T>
public ref class CRC abstract
{
public:
CRC()
{
//初始化crc算法设置
InitCRCSettings();
CRC_Table=nullptr;
CRC_Mask = ( ( ( (T)1<<(m_order-1) )-1 )<<1 )|1;
CRC_HighBit =( (T)1<<(m_order-1) );
CheckSettings();//检查设置
//初始化CRC Table
InitCRCTable();
//计算初值
Count_CRCInit_direct();
}
private:
/// <summary>
/// 初始化CRC table
/// </summary>
void InitCRCTable()
{
if(CRC_Table!=nullptr) return;
CRC_Table = gcnew array<T>(256);
int i,j;
T bit, crc;
for(i=0;i<256;i++)
{
crc=i;
if (m_refin) crc=reflect(crc, 8);
crc<<= m_order-8;
for (j=0; j<8; j++)
{
bit = crc & CRC_HighBit;
crc<<= 1;
if (bit) crc^= m_polynom;
}
if (m_refin) crc = reflect(crc, m_order);
crc&= CRC_Mask;
CRC_Table[i]= crc;
}
}
//将一个值crc的低bitnum位进行反转.
T reflect (T crc, int bitnum)
{
// reflects the lower 'bitnum' bits of 'crc'
T i, j=1, crcout=0;
for (i=( (T)1<<(bitnum-1) ); i; i>>=1)
{
if (crc & i) crcout|=j;
j<<= 1;
}
return crcout;
}
//计算直接初值
void Count_CRCInit_direct()
{
if(m_direct) //direct
{
CRCInit_direct=m_crcinit;
return;
}
T crc = m_crcinit;
for (int i=0; i<m_order; i++)
{
T bit = crc & CRC_HighBit;
crc<<= 1;
if (bit) crc^= m_polynom;
}
CRCInit_direct = crc & CRC_Mask;
}
protected:
//初始化crc设置
virtual void InitCRCSettings() abstract;
//检查crc设置
void CheckSettings()
{
if(m_order<1 || m_order>64)
Debug::Fail("ERROR,invalid order!");
if (m_polynom != (m_polynom & CRC_Mask))
Debug::Fail("ERROR,invalid polynom!");
if (m_crcinit != (m_crcinit & CRC_Mask))
Debug::Fail("ERROR,invalid crcinit!");
if (m_crcxor != (m_crcxor & CRC_Mask))
Debug::Fail("ERROR,invalid crcxor!");
}
private:
array<T>^ CRC_Table;//crc table
T CRC_Mask;//mask值,好比crc8为0xff
T CRC_HighBit;//CRC的最高位 好比crc8为0x80
//直接用来计算crc的初值 m_direct=1时就是m_crcinit m_direct时进行Count_CRCInit_direct计算
T CRCInit_direct;
protected:
//crc的设置.选用一个crc算法时,子类必须设置这些值
int m_order;//CRC多项式的阶数 1到64
T m_polynom;//CRC多项式
T m_crcinit;//CRC的初值
T m_crcxor;//和最终结果xor的值
int m_refin;//0或者1,表示输入在处理前是否反转
int m_refout;//0或者1,表示输出结果是否反转
int m_direct;//0或者1,1表示直接使用m_crcinit
public:
/// <summary>
/// 计算获得CRC值
/// </summary>
T GetCRC(array<Byte>^ pBuffer, int Length)
{
T crc = CRCInit_direct;
if (m_refin)
crc = reflect(crc, m_order);
Byte ValueByte;
for (int i=0;i<Length;i++)
{
ValueByte=pBuffer[i];
if(!m_refin)
crc = (crc << 8) ^ CRC_Table[(int) (( (crc>>(m_order-8) ) & 0xff) ^ ValueByte)];
else
crc = (crc >> 8) ^ CRC_Table[(int) ((crc & 0xff) ^ ValueByte)];
}
if (m_refout^m_refin)
crc = reflect(crc, m_order);
crc = (crc ^m_crcxor) & CRC_Mask;
return crc;
}
};
//宏
#define IMPLEMENT_GETCRC(_GETCRC_RETURN) \
_GETCRC_RETURN GetCRC(array<Byte>^ pBuffer, int Length) \
{ \
return CRC::GetCRC(pBuffer, Length); \
}
/// <summary>
/// CRC-8 名称:CRC-8-ATM
/// 0x7=x8 + x2 + x + 1
/// </summary>
public ref class CRC8_ATM:CRC<Byte>
{
public:
IMPLEMENT_GETCRC(Byte)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 8;
m_polynom = 0x7;
m_crcinit = 0x0;
m_crcxor = 0x0;
m_refin = 0;
m_refout= 0;
m_direct=1;
}
};
/// <summary>
/// CRC-8 名称:CRC-8-Dallas/Maxim
/// 0x31=X(8)+X(5)+X(4)+X(0)
/// </summary>
public ref class CRC8_Dallas:CRC<Byte>
{
public:
IMPLEMENT_GETCRC(Byte)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 8;
m_polynom = 0x31;
m_crcinit = 0x0;
m_crcxor = 0x0;
m_refin = 1;
m_refout= 1;
m_direct=1;
}
};
/// <summary>
/// CRC-16 名称:CRC-16-IBM,也即一般讲的CRC16
/// 0x8005=x16 + x15 + x2 + 1
/// </summary>
public ref class CRC16:CRC<UInt16>
{
public:
IMPLEMENT_GETCRC(UInt16)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 16;
m_polynom = 0x8005;
m_crcinit = 0x0;
m_crcxor = 0x0;
m_refin = 1;
m_refout=1;
m_direct=1;
}
};
/// <summary>
/// CRC-16-CCITT ,也即一般讲的CRC-CCITT
/// 0x1021=x16 + x12 + x5 + 1
/// </summary>
public ref class CRC16_CCITT:CRC<UInt16>
{
public:
IMPLEMENT_GETCRC(UInt16)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 16;
m_polynom = 0x1021;
m_crcinit = 0xFFFF;
m_crcxor = 0x0;
m_refin = 0;
m_refout=0;
m_direct=1;
}
};
/// <summary>
/// CRC-16-XKERMIT,用于xmodem协议
/// 0x8408=x16+x15 + x10 + x3
/// </summary>
public ref class CRC16_XKERMIT:CRC<UInt16>
{
public:
IMPLEMENT_GETCRC(UInt16)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 16;
m_polynom = 0x8408;
m_crcinit = 0;
m_crcxor = 0x0;
m_refin = 1;
m_refout=1;
m_direct=1;
}
};
/// <summary>
/// CRC-32 名称:CRC-32-IEEE 802.3,也即一般的CRC32/FCS32
/// 0x04C11DB7 = x32 + x26 + x23 + x22 + x16 + x12 +
/// x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
/// </summary>
public ref class CRC32:CRC<UInt32>
{
public:
IMPLEMENT_GETCRC(UInt32)
protected:
//初始化crc设置
virtual void InitCRCSettings() override
{
m_order = 32;
m_polynom = 0x4c11db7;
m_crcinit = 0xFFFFFFFF;
m_crcxor = 0xFFFFFFFF;
m_refin = 1;
m_refout=1;
m_direct=1;
}
};
/// <summary> /// CRC-64 CRC-64-ECMA-182 /// 0x42F0E1EBA9EA3693 = x^{64} + x^{62} + x^{57} + x^{55} + x^{54} + x^{53} + x^{52} + /// x^{47} + x^{46} + x^{45} + x^{40} + x^{39} + x^{38} + x^{37} + x^{35} /// + x^{33} +x^{32} + x^{31} + x^{29} + x^{27} + x^{24} + x^{23} + x^{22} + /// x^{21} + x^{19} + x^{17} + x^{13} + x^{12} + x^{10} + x^9 + x^7 + x^4 + x + 1 /// </summary> public ref class CRC64_ECMA:CRC<UInt64> { public: IMPLEMENT_GETCRC(UInt64) protected: //初始化crc设置 virtual void InitCRCSettings() override { m_order = 64; m_polynom = 0x42F0E1EBA9EA3693; m_crcinit=0xFFFFFFFFFFFFFFFF; m_crcxor=0xFFFFFFFFFFFFFFFF; m_refin = 0; m_refout = 0; m_direct = 1; } }; }}}