您的位置:首页 > 其它

关于CRC的简单总结

2012-04-06 17:19 309 查看
CRC码的生成步骤:

1.如果需要做16位的CRC校验,则需要将x的最高次幂为16生成多项式G(X)转换成对应的17位二进制数

G(X)=1+X(1)+X(3)+X(10)+X(13)+X(15)+X(16)

对应二进制码:1 1010 0100 0000 1011

2.将信息码左移16位

3.用生成多项式(二进制数)对信息码做除,得到16位的余数,模2除法 mod(x,y)= x - y * floor(x/y)

4.将余数拼到信息码左移后空出的位置,得到完整的CRC码

直接上代码:

////////////////////////////////////////////
/*
Author:闲云
Time:2012/04/06
转载或使用该代码,请注明出处,谢谢。。。
*/
////////////////////////////////////////////


void CCRC24Dlg::OnBtnCalCrc24()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CString strTips;
strTips=CRC24(m_strMD,m_strGD);
MessageBox(strTips);
}

/*////////////////////////////////////////////////////////////////////////
功能:十六进制转为十进制
输入:char chData//需要转换的十六进制数,结合本需求,只考虑了一位的
输出:int iDataTemp//转换后的十进制数
////////////////////////////////////////////////////////////////////////*/
int CCRC24Dlg::HexTODec(char chData)
{
int iDataTemp=0;
if('0'<=chData&&chData<='9'){
iDataTemp=chData+iDataTemp*16-'0';
}
else if('a'<=chData&&chData<='z'){
iDataTemp=chData+iDataTemp*16-'a'+10;
}
else if('A'<=chData&&chData<='Z'){
iDataTemp=chData+iDataTemp*16-'A'+10;
}
return iDataTemp;
}

/*////////////////////////////////////////////////////////////////////////
功能:十进制转为二进制
输入:int iDecData//需要转换的十进制数
输出:CString strData//转换后的二进制字符串
////////////////////////////////////////////////////////////////////////*/
CString CCRC24Dlg::DecToBin(int iDecData)
{
int i,iDataLen;
CString strDataTemp,strData,strTemp;
for(i=0;iDecData/2!=0;i++){
strTemp.Format("%d",iDecData%2);
strDataTemp+=strTemp;
iDecData=iDecData/2;
}
strTemp.Format("%d",iDecData);
strDataTemp+=strTemp;

iDataLen=strDataTemp.GetLength();
for (i=4;i>iDataLen;i--)
{
strData+="0";
}
for (i=0;i<iDataLen;i++)
{
strData+=strDataTemp[iDataLen-i-1];
}

return strData;
}

/*////////////////////////////////////////////////////////////////////////
功能:清除二进制字符串中第一位不为1的位
输入:CString strTemp//被处理前的二进制字符串
输出:CString strTemp//被处理后的二进制字符串
////////////////////////////////////////////////////////////////////////*/
CString CCRC24Dlg::InitClear(CString strTemp)
{
for (int j=0;j<strTemp.GetLength();j++)
{
if (strTemp[j]=='1')
{
strTemp=strTemp.Right(strTemp.GetLength()-j);
break;
}
else if (j==strTemp.GetLength()-1)
{
strTemp="2";
}
}
return strTemp;
}

/*////////////////////////////////////////////////////////////////////////
功能:异或运算
输入:CString strData1//做异或运算的第一个二进制字符串
CString strData2//做异或运算的第二个二进制字符串
int lenGD//异或运算的位数;除数的位数;CRC的生成项的位数
输出:CString strResult//异或运算后的二进制字符串
////////////////////////////////////////////////////////////////////////*/
CString CCRC24Dlg::MXORD(CString strData1,CString strData2,int lenGD)
{
CString strResult;
for (int i=0;i<lenGD;i++)
{
if(strData1[i] != strData2[i])
{ //相异的时候为1
strResult += '1';
}
else
{   //相同则为0
strResult += '0';
}
}
return strResult;
}

/*////////////////////////////////////////////////////////////////////////
功能:二进制转为十六进制
输入:CString strBin//需要转换的十六进制数
//结合本需求,只考虑了一位的十六进制数
输出:char chData//转换后得到的十六进制数
////////////////////////////////////////////////////////////////////////*/
char CCRC24Dlg::BinToHex(CString strBin)
{
int i=0,iDec=0;
CString strHex;
for(i=0;i<strBin.GetLength();i++)
{
iDec=strBin[i]+iDec*2-'0';
}

char chData;
switch(iDec%16)
{
case 0:
chData='0';
break;
case 1:
chData='1';
break;
case 2:
chData='2';
break;
case 3:
chData='3';
break;
case 4:
chData='4';
break;
case 5:
chData='5';
break;
case 6:
chData='6';
break;
case 7:
chData='7';
break;
case 8:
chData='8';
break;
case 9:
chData='9';
break;
case 10:
chData='A';
break;
case 11:
chData='B';
break;
case 12:
chData='C';
break;
case 13:
chData='D';
break;
case 14:
chData='E';
break;
case 15:
chData='F';
break;
}
return chData;
}

/*////////////////////////////////////////////////////////////////////////
功能:计算CRC24
输入:CString strMDHex//需要计算crc的十六进制字符串
CString strGDBin//计算crc的生成项的二进制字符串
输出:模2除法得到余数,以二进制字符串形式显示
////////////////////////////////////////////////////////////////////////*/
CString CCRC24Dlg::CRC24(CString strMDHex, CString strGDBin)
{
//////////////每一位十六进制转为对应二进制////////
CString strMD;
for (int i=0;i<strMDHex.GetLength();i++)
{
int iTemp=HexTODec(strMDHex[i]);
strMD+=DecToBin(iTemp);
}
//////////////模2除法得到余数////////////////////
int j=0;
int lenGD=strGDBin.GetLength();
CString strResultTemp,strResult;
for (j=0;j<lenGD-1;j++)
{
strMD+="0";
}
do
{
strMD=InitClear(strMD);//清除第一位不为1的位
strResultTemp=strMD.Left(lenGD);
if ("2"==strResultTemp)
{
strMD.Format("%s",_T("0"));
}
else
{
strMD=strMD.Right(strMD.GetLength()-lenGD);

strResultTemp=MXORD(strResultTemp,strGDBin,lenGD);
strResult=strResultTemp;//最终余数
strResultTemp=InitClear(strResultTemp);
if ("2"!=strResultTemp)
{
strResultTemp+=strMD;
strMD=strResultTemp;
}
}
} while (strMD.GetLength()>=lenGD);
///////////补位成所需要的位数/////////////////////
CString strCRC,strHex;
for (j=strMD.GetLength();j<lenGD-1;j++)
{
strCRC+="0";
}
strCRC+=strMD;

return strCRC;
}
上面的函数已经完全可以实现我们的需求了,如果你比我还懒,不要紧,现在给你Demo的下载地址:

http://download.csdn.net/detail/nanfeiyannan/4204674

测试用例:

十六进制信息码:590--0101 1001 0000,生成项:11001

信息码左移4位补0:0101 1001 0000 0000

模2除法过程:

01011 00100000000

10110 0100000000

11001____________

01111 0100000000
11110 100000000

11001____________

00111 100000000
11110 0000000

11001____________

00111 0000000

11100 00000

11001[u]____________[/u]
00101 00000

10100 000

11001[u]____________[/u]

01101 000

11010 00

11001[u]____________[/u]

00011 00

1100

1100即为模2除法的最终余数

所以最终CRC码为:0101 1001 0000 1100

如果算法有不对的地方,还望高手指点下。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: