首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ISO/ISO 13239 CRC16实现

ISO/ISO 13239 CRC16实现
EN

Stack Overflow用户
提问于 2013-08-20 08:45:00
回答 3查看 9K关注 0票数 4

我需要一个NFC标记的CRC16实现。正如标准告诉我的那样,这是ISO/ISO 13239,并提供了一个示例C代码。我把这段代码翻译成了Java,但是它给了我错误的结果:

代码语言:javascript
复制
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;
}

正如标准告诉我的那样,1,2,3,4的字节序列应该创建0x3991的CRC值,C版本在第42页:http://www.waazaa.org/download/fcd-15693-3.pdf

还有其他的CRC实现不起作用:crc16实现java第一个给我0x9e33,第二个0x0FA1 (顺便说一句0xE1E5)

是否有人在我的示例中发现错误,或者是否有另一个真正有效的CRC16实现?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-20 11:05:59

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

代码语言:javascript
复制
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;
}
票数 5
EN

Stack Overflow用户

发布于 2013-08-20 09:23:41

首先,PDF有:

代码语言:javascript
复制
#define POLYNOMIAL 0x8408 // x^16 + x^12 + x^5 + 1

当你有

代码语言:javascript
复制
private static final char POLYNOMIAL = 0x8404;

这肯定会引起问题

我有点担心,他们说0x8408等价于x^16 + x^12 + x^5 + 1,因为它不是,那个多项式将由0x8811表示。0x8408表示不太可能正确的x^16 + x^11 + x^4,因为它既不是素数n‘,也不是原语。就这一点而言,0x8404也是如此。

票数 2
EN

Stack Overflow用户

发布于 2015-08-08 02:18:59

下面是一个更快的实现(来源)。

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

代码语言:javascript
复制
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; }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18330692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档