4

I need a CRC16 implementation for NFC Tags. As the standard tolds me this is ISO/IEC13239 and a sample C code is provided. I translated this code into Java but it gives me wrong results:

private static final char POLYNOMIAL = 0x8404;
private static final char PRESET_VALUE = 0xFFFF;

public static int crc16(byte[] data) {
char current_crc_value = PRESET_VALUE;
for (int i = 0; i < data.length; i++) {
    current_crc_value = (char) (current_crc_value ^ ((char) data[i]));
    for (int j = 0; j < 8; j++) {
    if ((current_crc_value & 0x0001) == 0x0001) {
        current_crc_value = (char) ((current_crc_value >>> 1) ^ POLYNOMIAL);
    } else {
        current_crc_value = (char) (current_crc_value >>> 1);
    }
    }
}
current_crc_value = (char) ~current_crc_value;

return current_crc_value;
}

As the standard tells me a byte sequence of 1,2,3,4 should create a CRC Value of 0x3991 A C Version is here on Page 42: http://www.waazaa.org/download/fcd-15693-3.pdf

Also other CRC Implementations does not work: crc16 implementation java The first gives me 0x9e33, the second 0x0FA1 (my implementation by the way says 0xE1E5)

Does someone find an error in my sample or is there another CRC16 Implementation thats really works?

4

3 回答 3

5

您的答案非常接近,但我认为掩蔽和多项式可能存在一些问题。以下是一些似乎对我有用的调整:

private static final int POLYNOMIAL   = 0x8408;
private static final int PRESET_VALUE = 0xFFFF;

public static int crc16(byte[] data)
{
  int current_crc_value = PRESET_VALUE;
  for (int i = 0; i < data.length; i++ )
  {
    current_crc_value ^= data[i] & 0xFF;
    for (int j = 0; j < 8; j++)
    {
      if ((current_crc_value & 1) != 0)
      {
        current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
      }
      else
      {
        current_crc_value = current_crc_value >>> 1;
      }
    }
  }
  current_crc_value = ~current_crc_value;

  return current_crc_value & 0xFFFF;
}
于 2013-08-20T11:05:59.480 回答
2

首先 - PDF 有:

#define POLYNOMIAL 0x8408 // x^16 + x^12 + x^5 + 1

当你有

private static final char POLYNOMIAL = 0x8404;

这肯定会导致问题 - 请解决这个问题并让我们知道这是否是问题所在。

我有点担心他们说这0x8408等于 x^16 + x^12 + x^5 + 1因为它不是,所以多项式将由 表示0x88110x8408将表示x^16 + x^11 + x^4哪个不太可能是正确的,因为它既不是素数也不是原始的。就此而言,两者都不是0x8404

于 2013-08-20T09:23:41.463 回答
0

这是一个更快的实现(source)。

与初始值 0xFFFF 一起使用ccittPoly并补充结果。这为 0x3991 提供了new byte[]{1, 2, 3, 4}.

public class Crc16 {

// Generator polynom codes:
public static final int stdPoly    = 0xA001; // standard CRC-16 x16+x15+x2+1 (CRC-16-IBM)
public static final int stdRPoly   = 0xC002; // standard reverse x16+x14+x+1 (CRC-16-IBM)
public static final int ccittPoly  = 0x8408; // CCITT/SDLC/HDLC X16+X12+X5+1 (CRC-16-CCITT)
   // The initial CRC value is usually 0xFFFF and the result is complemented.
public static final int ccittRPoly = 0x8810; // CCITT reverse X16+X11+X4+1   (CRC-16-CCITT)
public static final int lrcPoly    = 0x8000; // LRCC-16 X16+1

private short[] crcTable;

public Crc16 (int polynom) {
   crcTable = genCrc16Table(polynom); }

public int calculate (byte[] data, int initialCrcValue) {
   int crc = initialCrcValue;
   for (int p = 0; p < data.length; p++) {
      crc = (crc >> 8) ^ (crcTable[(crc & 0xFF) ^ (data[p] & 0xFF)] & 0xFFFF); }
   return crc; }

private static short[] genCrc16Table (int polynom) {
   short[] table = new short[256];
   for (int x = 0; x < 256; x++) {
      int w = x;
      for (int i = 0; i < 8; i++) {
         if ((w & 1) != 0) {
            w = (w >> 1) ^ polynom; }
          else {
            w = w >> 1; }}
      table[x] = (short)w; }
   return table; }

}
于 2015-08-08T02:18:59.210 回答