我需要NFC标签的CRC16实现。正如标准告诉我的那样,这是ISO / IEC13239并提供了样本C代码。 我将这段代码翻译成了Java,但它给了我错误的结果:
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值
第42页的C版本:http://www.waazaa.org/download/fcd-15693-3.pdf
其他CRC实现也不起作用:crc16 implementation java
第一个给我0x9e33
,第二个给0x0FA1
(顺便说一下我的实现0xE1E5
)
有人在我的样本中发现错误,或者是否有其他CRC16实现真的有效?
答案 0 :(得分: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;
}
答案 1 :(得分: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
,因为它不是,多项式将由0x8811
表示。 0x8408
代表x^16 + x^11 + x^4
,它不太可能是正确的,因为它既不是素数也不是原始的。就此而言,0x8404
都不是。{/ p>
答案 2 :(得分:0)
这是一个更快的实现(source)。
使用初始值为0xFFFF的ccittPoly
并补充结果。这为new byte[]{1, 2, 3, 4}
提供了0x3991。
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; }
}