JAVA实现CRC16算法

来源:互联网 发布:校友会网站 源码 编辑:程序博客网 时间:2024/05/22 11:56
public static int get_crc16 (byte[] bufData, int buflen, byte[] pcrc)
{
int ret = 0;
int CRC = 0x0000ffff;
int POLYNOMIAL = 0x0000a001;
int i, j;




if (buflen == 0)
{
return ret;
}
for (i = 0; i < buflen; i++)
{
CRC ^= ((int)bufData[i] & 0x000000ff);
for (j = 0; j < 8; j++)
{
if ((CRC & 0x00000001) != 0)
{
CRC >>= 1;
CRC ^= POLYNOMIAL;
}
else
{
CRC >>= 1;
}
}
//System.out.println(Integer.toHexString(CRC));
}

System.out.println(Integer.toHexString(CRC));
pcrc[0] = (byte)(CRC & 0x00ff);
pcrc[1] = (byte)(CRC >> 8);


return ret;
}
/**
* @param args
*/
public static void main(String[] args) {
byte[] aa = {0x30,0x30,0x34,0x36,0x46,0x44,0x36,0x30,0x30,0x30,0x01,0x72,0x65,
0x66,0x65,0x72,0x69,0x6E,0x66,0x6F,0x2E,0x63,0x73,0x76,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x01,(byte)0xf4,0x01};
byte[] bb = new byte[3];
Crc16.get_crc16(aa, aa.length, bb);

System.out.println(Integer.toHexString((int)bb[0] & 0x000000ff));
System.out.println(Integer.toHexString((int)bb[1] & 0x000000ff));




}



/*
 * crc校验,输入一个数组,返回一个数组,返回的数组比原数组
 * 多了两个字节,也就是两个校验码,低字节在前,高字节在后.
 */
public class CRC16 {
 public static int[] crc(int[] data){
  int[] temdata=new int[data.length+2];
  //unsigned char alen = *aStr – 2;   //CRC16只计算前两部分       
   int xda , xdapoly ;           
   int i,j, xdabit ;            
   xda = 0xFFFF ;  
  xdapoly = 0xA001 ; // (X**16 + X**15 + X**2 + 1)   
  for(i=0;i<data.length;i++)         
  {         
  xda ^= data[i] ; 
  for(j=0;j<8;j++) {         
   xdabit =( int )(xda & 0x01) ;         
   xda >>= 1 ; 
  if( xdabit==1 ) 
   xda ^= xdapoly ; 
   }        
  }    
  System.arraycopy(data, 0, temdata, 0, data.length);
  temdata[temdata.length-2] = (int)(xda & 0xFF) ;           
  temdata[temdata.length-1] = (int)(xda>>8) ;     
  return temdata;
  }

//这个主函数用来测试用的
 public static void main(String args[]){
  int[] data={12,25,1,4,10,5,47,2,45,2,3,4,7,5,6,2,45};
  int[] d1=crc(data);
  for(int i=0;i<d1.length;i++)
   System.out.print(d1[i]+" ");
  System.out.println();
  int[] d2=crc(d1);
  for(int i=0;i<d2.length;i++)
   System.out.print(d2[i]+" ");
 }

}

==================================================================================

下面是C++的算法和参考源代码;

4 校验码       
CRC码由发送端计算,放置于发送信息报文的尾部。接收信息的设备再重新计算接收到信息报文的CRC,比较计算得到 
的CRC是否与接收到的相符,如果两者不相符,则表明出错。        
校验码的计算多项式为(X16 + X15 + X2 + 1)。        
具体CRC16码的 
计算方法是:         
1.预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器;       
2.把第一个8位二进制数据 (既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;       
3.把CRC寄存器的内容右移一 位(朝低位)用0填补最高位,并检查右移后的移出位;       
4.如果移出位为0:重复第3步(再次右移一位);          
   如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;       
5.重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;   
6.重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;       
7.将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;       
8.最后得到的CRC寄存器内容即为:CRC码。     

参考算法的C语言实现如下。以下程序 
计算一个报文的CRC16并填入报文最后两字节。       
void CRC16( unsigned char *aStr ){              
unsigned char alen = *aStr – 2;   //CRC16只计算前两部分       
unsigned int xda , xdapoly ;           
unsigned char i,j, xdabit ;            
 xda = 0xFFFF ;        
xdapoly = 0xA001 ; // (X**16 + X**15 + X**2 + 1)            
for(i=0;i<alen;i++)         
{         
xda ^= aStr[i] ;         
for(j=0;j<8;j++) {         
 xdabit =(unsigned char )(xda & 0x01) ;         
 xda >>= 1 ;          
if( xdabit ) 
 xda ^= xdapoly ;   
 }        
}               
aStr[alen-2] = (unsigned char)(xda & 0xFF) ;           
aStr[alen-1] = (unsigned char)(xda>>8) ;       
}

===============================================================================

以代码仅供参考,如有不明白或建议请联系我,共同交流,email:hnbcjzj@163.com

另外提供一个网上找的java crc校验的源程序,我没怎么研究,

import java.io.IOException;
 
public class CRC16Checker {
 
            private static int[] index = new int[] { 16, 15, 2, 0 };
 
            private static int[] getBinary(String text) {
                        StringBuffer num = new StringBuffer();
                        String s; char ch;
                        for (int i = 0; i < text.length(); i++) { // Change each char to binary code.
                                    s = Integer.toBinaryString(text.charAt(i));
                                    // If the code is less than 8 bit, make it as 8 bit.
                                    for (int j = 8 - s.length(); j > 0; j--) num.append(0);
                                    num.append(s);
                        }
                        int len = num.length();
                        int[] code = new int[len];
                        for (int i = 0; i < len; i++) // Change each 0/1 char to int.
                            code[i] = Character.getNumericValue(num.charAt(i));
                        return code;
            }
 
            private static String toHex(int[] num) {
                        StringBuffer hex = new StringBuffer(num.length / 4);
                        char[] ch = new char[4];
                        for (int i = 0; i < num.length;) {
                            // Change each 0/1 int to char.
                                    ch[0] = Character.forDigit(num[i++], 2);
                                    ch[1] = Character.forDigit(num[i++], 2);
                                    ch[2] = Character.forDigit(num[i++], 2);
                                    ch[3] = Character.forDigit(num[i++], 2);
                                    // Change each 4-bit-code to hex number.
                                    hex.append(Integer.toHexString(Integer.parseInt(String.valueOf(ch), 2)));
                        }
                        return hex.toString();
            }
 
// CRC codes main process
            public static int[] makeCRCCodes(int[] sourceCodes, int[] multinomial) {
                        // The lenght of CRC code is N bits longer than source code. The codes
                        // from 0 to sourceLength are same as the source. N bits after source
                        // are the CRC codes. N is decided by the multinomial.
                        // CRC码数组总长为原码长加上校验码码长。数组前部存放原码。校验码存放在数组
                        // 最后的N位。校验码长度决定于生成多项式数组0位置上的元素。
                        int sourceLength = sourceCodes.length;
                        int codesLength = sourceLength + multinomial[0];
                        int[] crcCodes = new int[codesLength];
                        // Copy source code from 0 to sourceLength. 拷贝原码。
                        System.arraycopy(sourceCodes, 0, crcCodes, 0, sourceLength);
                        int temp, pos;
                        // Division system. 除法器。
                        for (int i = 0; i < sourceLength; i++) {
                                    // Count value of the input adding the first register.
                                    // 用第i位原码和第一个寄存器值模二加。
                                    temp = (crcCodes[sourceLength] + sourceCodes[i]) % 2;
                                    // Move registers forwards from (1, length) to (0, length - 1).
                                    // 第二个寄存器及以后的所有寄存器值前移1位。
                                    System.arraycopy(
                                                crcCodes, sourceLength + 1, crcCodes, sourceLength, multinomial[0] - 1);
                                    // Set the last register with counted value.
                                    // 最后一个寄存器值存放计算好的输入值。
                                    crcCodes[codesLength - 1] = temp;
                                    // Count other registers. 按生成多项式的值算出位置,模二加出该寄存器的值。
                                    for (int j = index.length - 2; j > 0; j--) {
                                                pos = codesLength - multinomial[j] - 1;
                                                crcCodes[pos] = (crcCodes[pos] + temp) % 2;
                                    }
                        }
                        return crcCodes;
            }
 
            public static void main(String[] args) throws IOException {
                        System.out.print("Input hex data :");
                        StringBuffer buf = new StringBuffer();
                        char ch = (char) System.in.read();
                        while (ch != '/r' && ch != '/n') {
                                    buf.append(ch);
                                    ch = (char) System.in.read();
                        }
                        // Get binary codes.
                        int[] b = CRC16Checker.getBinary(buf.toString());
                        // Make CRC codes.
                        b = CRC16Checker.makeCRCCodes(b, CRC16Checker.index);
                        // Output code as binary number.
                        for (int i = 0; i < b.length;) {
                                    for (int j = 0; j < 4; j++, i++) System.out.print(b[i]);
                                    System.out.print(' ');
                        }
                        System.out.println();
                        // Output code as hex number.
                        System.out.println("The CRC16 code is :" + CRC16Checker.toHex(b));
            }
}


0 0
原创粉丝点击