关于CRC的简单总结

来源:互联网 发布:清华大学刘树红 知乎 编辑:程序博客网 时间:2024/05/22 14:24

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 hereUpdateData(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____________

00101 00000

10100 000

11001____________

01101 000

11010 00

11001____________

00011 00

1100

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

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

如果算法有不对的地方,还望高手指点下。。。

原创粉丝点击