2023-06-10
名称 | 生成多项式 | 简记式 | 标准引用 |
---|---|---|---|
CRC-4 | $x^4 + x + 1$ | 3 | ITU G.704 |
CRC-8 | $x^8 + x^5 + x^4 + 1$ | 0x31 | |
CRC-8 | $x^8 + x^2 + x + 1$ | 0x07 | |
CRC-8 | $x^8 + x^6 + x^4 + x^3 + x^2 + x$ | 0x5E | |
CRC-12 | $x^{12} + x^{11} + x^3 + x + 1$ | 0x80F | |
CRC-16 | $x^{16} + x^{15} + x^2 + 1$ | 0x8005 | IBM SDLC |
CRC16-CCITT | $x^{12} + x^{11} + x^3 + x + 1$ | 0x1021 | ISO HDLC, ITU X.25,,V.34/V.41/V.42, PPP-FCS |
CRC-32 | $x^{32} + x^{26} + x^{23} + … + x^2 + x + 1$ | 0x04C11DB7 | ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS |
CRC-32c | $x^{32} + x^{28} + x^{27} + … + x^8 + x^6 + 1$ | 0x1EDC6F41 | SCTP |
常用查表法和计算法。
计算法步骤如下:
/// 计算法
(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码。
/// 以上计算步骤中的多项式A001是8005按位翻转后的结果。
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// GetCrc16(data, 0x1021, true) -- CRC-16/MCRF4XX
/// GetCrc16(data, 0x1021, false) -- CRC-16/XMODEM
/// GetCrc16(data, 0x8005, true) -- CRC-16/MODBUS
/// GetCrc16(data, 0x8005, false) -- CRC-16/BUYPASS
/// Console.WriteLine($"crc1 = 0x{GetCrc16(data, 0x1021, false):X4}, crc2 = 0x{NewLife.SecurityHelper.Crc16(data):X4}"); crc1 = 0x5DC1, crc2 = 0x5DC1
/// Console.WriteLine($"crc1 = 0x{GetCrc16(data, 0x8005, true):X4}, crc2 = 0x{NewLife.Security.Crc16.Compute(stream, -1):X4}"); crc1 = 0xD63B, crc2 = 0xD63B
/// CRC-16
UInt16 GetCrc16(byte[] data, UInt16 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
UInt16 crc = 0xFFFF;
if (isReverse)
{
/// 逆序多项式
BitVector32 bits = new BitVector32((Int32)Poly);
BitVector32 reverse_bits = new BitVector32();
for (int i = 0; i < 32; i++)
{
reverse_bits[1 << (31 - i)] = bits[1 << i];
}
Poly = (UInt16)((reverse_bits.Data >> 16) & 0xffff);
crc = 0xFFFF;
for (UInt16 i = 0; i < data.Length; i++)
{
crc ^= data[i];
for (UInt16 j = 0; j < 8; j++)
{
if ((crc & 0x1) != 0)
{
crc = (UInt16)((crc >> 1) ^ Poly);
}
else
{
crc = (UInt16)(crc >> 1);
}
}
}
}
else
{
crc ^= crc;
for (UInt16 i = 0; i < data.Length; i++)
{
crc ^= (UInt16)(data[i] << 8);
for (UInt16 j = 0; j < 8; j++)
{
if ((crc & 0x8000) != 0)
{
crc = (UInt16)((crc << 1) ^ Poly);
}
else
{
crc = (UInt16)(crc << 1);
}
}
}
}
return crc;
}
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// GetCrc32(data, 0x04C11DB7, true) -- CRC-32
/// GetCrc32(data, 0x04C11DB7, false) -- CRC-32/POSIX
/// GetCrc32(data, 0x1EDC6F41, true) -- CRC-32C
/// Console.WriteLine($"crc1 = 0x{GetCrc32(data, 0x04C11DB7, true):X8}, crc2 = 0x{NewLife.Security.Crc32.Compute(data):X8}"); crc1 = 0x7B1B0DAA, crc2 = 0x7B1B0DAA
/// crc32
UInt32 GetCrc32(byte[] data, UInt32 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
UInt32 crc = 0xFFFFFFFF;
if (isReverse)
{
/// 逆序多项式
BitVector32 bits = new BitVector32((Int32)Poly);
BitVector32 reverse_bits = new BitVector32();
for (int i = 0; i < 32; i++)
{
reverse_bits[1 << (31 - i)] = bits[1 << i];
}
Poly = (UInt32)reverse_bits.Data;
crc = 0xFFFFFFFF;
for (UInt32 i = 0; i < data.Length; i++)
{
crc ^= data[i];
for (UInt32 j = 0; j < 8; j++)
{
if ((crc & 0x1) != 0)
{
crc = (UInt32)((crc >> 1) ^ Poly);
}
else
{
crc = (UInt32)(crc >> 1);
}
}
}
}
else
{
crc ^= crc;
for (UInt32 i = 0; i < data.Length; i++)
{
crc ^= (UInt32)(data[i] << 24);
for (UInt32 j = 0; j < 8; j++)
{
if ((crc & 0x80000000) != 0)
{
crc = (UInt32)((crc << 1) ^ Poly);
}
else
{
crc = (UInt32)(crc << 1);
}
}
}
}
return crc ^ 0xFFFFFFFF;
}
查表法步骤:
/// 查表法
查表法是将移位异或的计算结果做成了一个表,就是将0~256放入一个长度为16位的寄存器中的低八位,高八位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到八位全部移出,最后寄存器中的值就是表格中的数据,高八位、低八位分别单独一个表。
/// CRC-16
0x8005 = 1000 0000 0000 0101B
0xA001 = 1010 0000 0000 0001B
1、对比两个二进制高低位正好是完全倒序的,CRC校验分为正向校验与反向校验。正向校验高位在左,反向校验低位在左。
2、比如正向CRC校验的数据为0xAF5D=1010 1111 0101 1101B与0x8005异或时应该是0xAF5D^0x8005,而要使用0xA001与数据进行校验也应该使0xAF5D高低位换顺序为0xBAF5=1011 1010 1111 0101B。
3正向校验使用左移位,反向校验使用右移位,其实原理是一样的,得看校验的数据高低位顺序
/// crc16
UInt16[] GenerateCRC16Table(UInt16 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
UInt16[] crc_table = new UInt16[256];
if (isReverse)
{
/// 逆序多项式
BitVector32 bits = new BitVector32((Int32)Poly);
BitVector32 reverse_bits = new BitVector32();
for (int i = 0; i < 32; i++)
{
reverse_bits[1 << (31 - i)] = bits[1 << i];
}
Poly = (UInt16)((reverse_bits.Data >> 16) & 0xffff);
}
Parallel.For(0, 256, number =>
{
UInt16 crc;
if (isReverse)
{
crc = (UInt16)number;
for (UInt16 i = 0; i < 8; i++)
{
if ((crc & 0x1) != 0)
{
crc = (UInt16)((crc >> 1) ^ Poly);
}
else
{
crc = (UInt16)(crc >> 1);
}
}
}
else
{
crc = (UInt16)(number << 8);
for (UInt16 i = 0; i < 8; i++)
{
if ((crc & 0x8000) != 0)
{
crc = (UInt16)((crc << 1) ^ Poly);
}
else
{
crc = (UInt16)(crc << 1);
}
}
}
crc_table[number] = crc;
});
return crc_table;
}
/// crc32
UInt32[] GenerateCRC32Table(UInt32 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
UInt32[] crc_table = new UInt32[256];
if (isReverse)
{
/// 逆序多项式
BitVector32 bits = new BitVector32((Int32)Poly);
BitVector32 reverse_bits = new BitVector32();
for (int i = 0; i < 32; i++)
{
reverse_bits[1 << (31 - i)] = bits[1 << i];
}
Poly = (UInt32)reverse_bits.Data;
}
Parallel.For(0, 256, number =>
{
UInt32 crc;
if (isReverse)
{
crc = (UInt32)number;
for (UInt32 i = 0; i < 8; i++)
{
if ((crc & 0x1) != 0)
{
crc = (UInt32)((crc >> 1) ^ Poly);
}
else
{
crc = (UInt32)(crc >> 1);
}
}
}
else
{
crc = (UInt32)(number << 24);
for (UInt32 i = 0; i < 8; i++)
{
if ((crc & 0x80000000) != 0)
{
crc = (UInt32)((crc << 1) ^ Poly);
}
else
{
crc = (UInt32)(crc << 1);
}
}
}
crc_table[number] = crc;
});
return crc_table;
}
/// 测试代码
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// Stream stream = new MemoryStream(data);
/// Console.WriteLine($"GetCrc16(data, 0x1021, false) = 0x{GetCrc16(data, 0x1021, false):X4}.");
/// Console.WriteLine($"GetCrc16_Table(data, crc_2, false) = 0x{GetCrc16_Table(data, crc_2, false):X4}.");
/// Console.WriteLine($"NewLife.SecurityHelper.Crc16(data) = 0x{NewLife.SecurityHelper.Crc16(data):X4}.");
/// Console.WriteLine($"GetCrc16(data, 0x8005, true) = 0x{GetCrc16(data, 0x8005, true):X4}.");
/// Console.WriteLine($"GetCrc16_Table(data, crc_3, true) = 0x{GetCrc16_Table(data, crc_3, true):X4}.");
/// Console.WriteLine($"NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length) = 0x{NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length):X4}.");
/// 输出结果
/// GetCrc16(data, 0x1021, false) = 0x5DC1.
/// GetCrc16_Table(data, crc_2, false) = 0x5DC1.
/// NewLife.SecurityHelper.Crc16(data) = 0x5DC1.
/// GetCrc16(data, 0x8005, true) = 0xD63B.
/// GetCrc16_Table(data, crc_3, true) = 0xD63B.
/// NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length) = 0xD63B.
UInt16 GetCrc16_Table(byte[] data, UInt16[] crc_table, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
/// https://blog.csdn.net/weixin_44256803/article/details/111794445
/// https://blog.csdn.net/qq_25814297/article/details/109402108
UInt16 crc = 0xFFFF;
if (isReverse)
{
for (UInt16 i = 0; i < data.Length; i++)
{
crc = (UInt16)((crc >> 8) ^ crc_table[(crc ^ data[i]) & 0xFF]);
}
}
else
{
crc ^= crc;
for (UInt16 i = 0; i < data.Length; i++)
{
crc = (UInt16)((crc << 8) ^ crc_table[(crc >> 8 ^ data[i]) & 0xFF]);
}
}
return crc;
}
/// 测试代码
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// Stream stream = new MemoryStream(data);
/// UInt32[] crc32_1 = GenerateCRC32Table(0x04C11DB7, true);
/// Console.WriteLine($"GetCrc32(data, 0x04C11DB7, true) = 0x{GetCrc32(data, 0x04C11DB7, true):X4}.");
/// Console.WriteLine($"GetCrc32_Table(data, crc32_1, false) = 0x{GetCrc32_Table(data, crc32_1, true):X4}.");
/// Console.WriteLine($"NewLife.Security.Crc32.Compute(data, 0, data.Length) = 0x{NewLife.Security.Crc32.Compute(data, 0, data.Length):X4}.");
/// 输出结果
/// GetCrc32(data, 0x04C11DB7, true) = 0x7B1B0DAA.
/// GetCrc32_Table(data, crc32_1, false) = 0x7B1B0DAA.
/// NewLife.Security.Crc32.Compute(data, 0, data.Length) = 0x7B1B0DAA.
UInt32 GetCrc32_Table(byte[] data, UInt32[] crc_table, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
UInt32 crc = 0xFFFFFFFF;
if (isReverse)
{
for (UInt16 i = 0; i < data.Length; i++)
{
crc = (UInt32)((crc >> 8) ^ crc_table[(crc ^ data[i]) & 0xFF]);
}
}
else
{
crc ^= crc;
for (UInt16 i = 0; i < data.Length; i++)
{
crc = (UInt32)((crc << 8) ^ crc_table[(crc >> 24 ^ data[i]) & 0xFF]);
}
}
return crc ^ 0xFFFFFFFF;
}
crc算法可灵活设置Init初始化值、Poly多项式值、RefIn/RefOut是否倒序、XorOut结果异或等参数计算出不同结果。后期如需计算其它类型crc,可参照CRC在线计算
uint8_t crc4_itu(uint8_t *data, uint_len length);
uint8_t crc5_epc(uint8_t *data, uint_len length);
uint8_t crc5_itu(uint8_t *data, uint_len length);
uint8_t crc5_usb(uint8_t *data, uint_len length);
uint8_t crc6_itu(uint8_t *data, uint_len length);
uint8_t crc7_mmc(uint8_t *data, uint_len length);
uint8_t crc8(uint8_t *data, uint_len length);
uint8_t crc8_itu(uint8_t *data, uint_len length);
uint8_t crc8_rohc(uint8_t *data, uint_len length);
uint8_t crc8_maxim(uint8_t *data, uint_len length);
uint16_t crc16_ibm(uint8_t *data, uint_len length);
uint16_t crc16_maxim(uint8_t *data, uint_len length);
uint16_t crc16_usb(uint8_t *data, uint_len length);
uint16_t crc16_modbus(uint8_t *data, uint_len length);
uint16_t crc16_ccitt(uint8_t *data, uint_len length);
uint16_t crc16_ccitt_false(uint8_t *data, uint_len length);
uint16_t crc16_x25(uint8_t *data, uint_len length);
uint16_t crc16_xmodem(uint8_t *data, uint_len length);
uint16_t crc16_dnp(uint8_t *data, uint_len length);
uint32_t crc32(uint8_t *data, uint_len length);
uint32_t crc32_mpeg_2(uint8_t *data, uint_len length);
/******************************************************************************
* Name: CRC-4/ITU x4+x+1
* Poly: 0x03
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc4_itu(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x0C;// 0x0C = (reverse 0x03)>>(8-4)
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-5/EPC x5+x3+1
* Poly: 0x09
* Init: 0x09
* Refin: False
* Refout: False
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc5_epc(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0x48; // Initial value: 0x48 = 0x09<<(8-5)
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x48; // 0x48 = 0x09<<(8-5)
else
crc <<= 1;
}
}
return crc >> 3;
}
/******************************************************************************
* Name: CRC-5/ITU x5+x4+x2+1
* Poly: 0x15
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc5_itu(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x15;// 0x15 = (reverse 0x15)>>(8-5)
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-5/USB x5+x2+1
* Poly: 0x05
* Init: 0x1F
* Refin: True
* Refout: True
* Xorout: 0x1F
* Note:
*****************************************************************************/
uint8_t crc5_usb(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0x1F; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x14;// 0x14 = (reverse 0x05)>>(8-5)
else
crc = (crc >> 1);
}
}
return crc ^ 0x1F;
}
/******************************************************************************
* Name: CRC-6/ITU x6+x+1
* Poly: 0x03
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc6_itu(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x30;// 0x30 = (reverse 0x03)>>(8-6)
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-7/MMC x7+x3+1
* Poly: 0x09
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
* Use: MultiMediaCard,SD,ect.
*****************************************************************************/
uint8_t crc7_mmc(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x12; // 0x12 = 0x09<<(8-7)
else
crc <<= 1;
}
}
return crc >> 1;
}
/******************************************************************************
* Name: CRC-8 x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc8(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x07;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-8/ITU x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x55
* Alias: CRC-8/ATM
*****************************************************************************/
uint8_t crc8_itu(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x07;
else
crc <<= 1;
}
}
return crc ^ 0x55;
}
/******************************************************************************
* Name: CRC-8/ROHC x8+x2+x+1
* Poly: 0x07
* Init: 0xFF
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8_t crc8_rohc(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0xFF; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xE0; // 0xE0 = reverse 0x07
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-8/MAXIM x8+x5+x4+1
* Poly: 0x31
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Alias: DOW-CRC,CRC-8/IBUTTON
* Use: Maxim(Dallas)'s some devices,e.g. DS18B20
*****************************************************************************/
uint8_t crc8_maxim(uint8_t *data, uint_len length)
{
uint8_t i;
uint8_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; i++)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8C; // 0x8C = reverse 0x31
else
crc >>= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/IBM x16+x15+x2+1
* Poly: 0x8005
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0x0000
* Alias: CRC-16,CRC-16/ARC,CRC-16/LHA
*****************************************************************************/
uint16_t crc16_ibm(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/MAXIM x16+x15+x2+1
* Poly: 0x8005
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Note:
*****************************************************************************/
uint16_t crc16_maxim(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
else
crc = (crc >> 1);
}
}
return ~crc; // crc^0xffff
}
/******************************************************************************
* Name: CRC-16/USB x16+x15+x2+1
* Poly: 0x8005
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Note:
*****************************************************************************/
uint16_t crc16_usb(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0xffff; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
else
crc = (crc >> 1);
}
}
return ~crc; // crc^0xffff
}
/******************************************************************************
* Name: CRC-16/MODBUS x16+x15+x2+1
* Poly: 0x8005
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0x0000
* Note:
*****************************************************************************/
uint16_t crc16_modbus(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0xffff; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/CCITT x16+x12+x5+1
* Poly: 0x1021
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0x0000
* Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT
*****************************************************************************/
uint16_t crc16_ccitt(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021
else
crc = (crc >> 1);
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/CCITT-FALSE x16+x12+x5+1
* Poly: 0x1021
* Init: 0xFFFF
* Refin: False
* Refout: False
* Xorout: 0x0000
* Note:
*****************************************************************************/
uint16_t crc16_ccitt_false(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0xffff; //Initial value
while(length--)
{
crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint6_t)(*data)<<8; data++;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x8000 )
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/X25 x16+x12+x5+1
* Poly: 0x1021
* Init: 0xFFFF
* Refin: True
* Refout: True
* Xorout: 0XFFFF
* Note:
*****************************************************************************/
uint16_t crc16_x25(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0xffff; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021
else
crc = (crc >> 1);
}
}
return ~crc; // crc^Xorout
}
/******************************************************************************
* Name: CRC-16/XMODEM x16+x12+x5+1
* Poly: 0x1021
* Init: 0x0000
* Refin: False
* Refout: False
* Xorout: 0x0000
* Alias: CRC-16/ZMODEM,CRC-16/ACORN
*****************************************************************************/
uint16_t crc16_xmodem(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x8000 )
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
/******************************************************************************
* Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1
* Poly: 0x3D65
* Init: 0x0000
* Refin: True
* Refout: True
* Xorout: 0xFFFF
* Use: M-Bus,ect.
*****************************************************************************/
uint16_t crc16_dnp(uint8_t *data, uint_len length)
{
uint8_t i;
uint16_t crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65
else
crc = (crc >> 1);
}
}
return ~crc; // crc^Xorout
}
/******************************************************************************
* Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
* Poly: 0x4C11DB7
* Init: 0xFFFFFFF
* Refin: True
* Refout: True
* Xorout: 0xFFFFFFF
* Alias: CRC_32/ADCCP
* Use: WinRAR,ect.
*****************************************************************************/
uint32_t crc32(uint8_t *data, uint_len length)
{
uint8_t i;
uint32_t crc = 0xffffffff; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
else
crc = (crc >> 1);
}
}
return ~crc;
}
/******************************************************************************
* Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
* Poly: 0x4C11DB7
* Init: 0xFFFFFFF
* Refin: False
* Refout: False
* Xorout: 0x0000000
* Note:
*****************************************************************************/
uint32_t crc32_mpeg_2(uint8_t *data, uint_len length)
{
uint8_t i;
uint32_t crc = 0xffffffff; // Initial value
while(length--)
{
crc ^= (uint32_t)(*data++) << 24;// crc ^=(uint32_t)(*data)<<24; data++;
for (i = 0; i < 8; ++i)
{
if ( crc & 0x80000000 )
crc = (crc << 1) ^ 0x04C11DB7;
else
crc <<= 1;
}
}
return crc;
}