我需要计算数据数组的CRC,该数据与_crc16_update
中avr-libc
函数的结果相同。
我理解_crc16_update
函数是:
uint16_t crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
return crc;
}
我在Android应用中的当前代码计算相同的CRC:
private short crc16Update( short crc, byte a )
{
short i;
crc ^= a;
for( i = 0; i < 8; ++i )
{
if ( (crc & 1) > 0 )
crc = (crc >>> 1) ^ 0xA001;
else
crc = (crc >>> 1);
}
return crc;
}
我用以下循环调用该方法(_hexBytes是包含数据的数组,_crc应该保存与avr-libc函数计算的CRC相同的值):
for( Byte b : _hexBytes )
_crc = crc16Update( _crc, b );
我在两端都没有得到相同的结果。任何人都可以在我的代码中看到错误来计算CRC吗?
以下是我使用的一些测试数据:
数据:[0x0c,0x94,0x39]
我的Java代码中的CRC:0x0827
来自avr-libc
代码的CRC:0xd16e
也许它与签署的Java短片有关?
答案 0 :(得分:0)
扔掉它并使用表格驱动版本,速度至少快8倍。你必须调整当然的参数,例如你的多项式是0xA001,它看起来像下面的POLYNOMIAL_IBM。
/**
* CRC16. An implementation of {@link java.util.zip.Checksum} for 16-bit cyclic redundancy checks.
*
*/
import java.util.zip.Checksum;
/**
* CRC16. An implementation of {@link java.util.zip.Checksum} for 16-bit cyclic redundancy checks.
*
* @author Esmond Pitt.
*/
public class CRC16 implements Checksum
{
public enum Algorithm
{
CRC_CCIT(POLYNOMIAL_CCITT, INIT_CCITT),
XMODEM(POLYNOMIAL_XMODEM, (short)0),
ARC(POLYNOMIAL_ARC, (short)0),
IBM(POLYNOMIAL_IBM, (short)0),
ANSI(POLYNOMIAL_IBM, (short)0);
Algorithm(int polynomial, short initialValue)
{
this.polynomial = polynomial;
this.initialValue = initialValue;
}
int polynomial;
short initialValue;
};
/**
* CRC-CCITT polynomial, used by X.25, V.41, Bluetooth, PPP, IrDA, BACnet; known as CRC-CCITT
*/
public static final int POLYNOMIAL_CCITT = 0x1021;
public static final short INIT_CCITT = (short)0xffff;
/**
* CRC-16 polynomial, used by XMODEM, USB, many others; also known as CRC-16
*/
public static final int POLYNOMIAL_IBM = 0xa001;
public static final int POLYNOMIAL_XMODEM = 0x8408;
public static final int POLYNOMIAL_ARC = 0x8005;
// private final int polynomial;
private final short init;
private final short[] crcTable = new short[256];
private short value;
/**
* Construct a CRC16-CCIT, with polynomial=0x1021 and initial value=0xffff.
*/
public CRC16()
{
this(Algorithm.CRC_CCIT);
}
/**
* COnstruct a polynomial specifying the algorithm.
*
* @param algorithm Algorithm
*/
public CRC16(Algorithm algorithm)
{
this(algorithm.polynomial, algorithm.initialValue);
}
/**
* Construct a CRC16 specifying the polynomial and initial value.
* @param polynomial Polynomial, typically one of the POLYNOMIAL_* constants.
* @param init Initial value, typically either 0xffff or zero.
*/
public CRC16(int polynomial, short init)
{
// this.polynomial = polynomial;
this.value = this.init = init;
for (int dividend = 0; dividend < 256; dividend++)
{
int remainder = dividend << 8;
for (int bit = 8; bit > 0; --bit)
if ((remainder & 0x8000) != 0)
remainder = (remainder << 1) ^ polynomial;
else
remainder <<= 1;
crcTable[dividend] = (short)remainder;
}
}
@Override
public void update(byte[] buffer, int offset, int len)
{
for (int i = 0; i < len; i++)
{
int data = buffer[offset+i] ^ (value >>> 8);
value = (short)(crcTable[data & 0xff] ^ (value << 8));
}
}
/**
* Updates the current checksum with the specified array of bytes.
* Equivalent to calling <code>update(buffer, 0, buffer.length)</code>.
* @param buffer the byte array to update the checksum with
*/
public void update(byte[] buffer)
{
update(buffer, 0, buffer.length);
}
@Override
public void update(int b)
{
update(new byte[]{(byte)b}, 0, 1);
}
@Override
public long getValue()
{
return value;
}
@Override
public void reset()
{
value = init;
}
/** Tester */
public static void main(String[] args)
{
byte[] data = new byte[]{0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
CRC16 crc16 = new CRC16();
crc16.update(data,0,data.length);
System.out.println("CCITT:\t\t\tinit=0xffff poly=0x1021 CRC16(\"123456789\")=0x29b1");
System.out.println("Calculated:\t\tinit=0x"+Integer.toHexString(INIT_CCITT & 0xffff)+" poly=0x"+Integer.toHexString(POLYNOMIAL_CCITT)+" CRC16(\"123456789\")=0x"+Long.toHexString(crc16.getValue()));
System.out.println("Test successful:\t"+(crc16.getValue() == 0x29b1));
String s = "hello";
crc16 = new CRC16(POLYNOMIAL_IBM, INIT_CCITT);
data = new byte[]{0x02, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
crc16.update(data, 0, data.length);
System.out.println("CRC16=0x"+Integer.toHexString((int)crc16.getValue() & 0xffff));
}
}