相信我,我曾试图对此进行编码,尝试了Google,并且没有任何运气。 我正在尝试使用此poly
实现CRC16x^16 + x^10 + x^8 + x^7 + x^3 + 1
使用C语言。由于我更了解PHP,我试图让函数继续运行,但我没有得到28713的正确答案。此代码生成的CRC为32713.
function crc16($string,$crc=0) {
for ( $x=0; $x<strlen( $string ); $x++ ) {
$crc = $crc ^ ord( $string[$x] );
echo $crc.'<br />';
for ($y = 0; $y < 8 ; $y++) {
if ( ($crc & 0x0001) == 0x0001 ) $crc = ( ($crc >> 1 ) ^ 0x10589 );
else $crc = $crc >> 1;
}
}
return $crc;
}
echo 'CRC:'.crc16('10100011');
我请求任何人提前帮助......谢谢你。
答案 0 :(得分:3)
一些CRC被定义为处理从MSB到LSB的每个字节的比特,并且一些被定义为处理从LSB到MSB的比特(后者通常是被描述为“反射”的顺序并且使用反转多项式)。您的代码将新位置于CRC的LSB端并向右移位,这适用于反射的CRC,但CRC-16-DECT似乎是未反映的CRC之一。
您输入的“10100011”表示二进制,但正在处理为8字节的ASCII字符串。
要看看将10100011视为二进制代码时会发生什么,并首先使用MSB,这是一个手动计算(因为8位输入不需要太多努力):
polynomial coefficients
|
| 10100010 <--- quotient (irrelevant)
v __________
10000010110001001 ) 10100011 <-------- input
^ 10000010110001001
-----------------
= 100001110001001
^ 10000010110001001
-----------------
= 101110101101
^ 10000010110001001
-----------------
remainder (CRC) -----> = 111000000101001
= 0x7029 = 28713
因此,将输入视为二进制并首先处理MSB是正确的做法。
这里有一些C代码可以完成这项工作(因为我不是真正使用PHP,最终你还想要C代码):
#include <stdio.h>
#include <stdint.h>
static uint16_t crc16(const uint8_t *data, size_t len)
{
size_t i, j;
uint16_t crc = 0;
for (i = 0; i < len; i++) {
crc ^= (data[i] << 8); /* data at top end, not bottom */
for (j = 0; j < 8; j++) {
if ((crc & 0x8000) == 0x8000) /* top bit, not bottom */
crc = (crc << 1) ^ 0x0589; /* shift left, not right */
else
crc <<= 1; /* shift left, not right */
}
}
return crc;
}
int main(void)
{
const uint8_t in[] = { 0xa3 }; /* = 10100011 in binary */
uint16_t crc = crc16(in, sizeof(in));
printf("%u (0x%x)\n", crc, crc);
return 0;
}
结果:
$ gcc -Wall -o crc16 crc16.c
$ ./crc16
28713 (0x7029)
$
答案 1 :(得分:0)
尝试将0x10589更改为0xA001:
function crc16($string,$crc=0) {
for ( $x=0; $x<strlen( $string ); $x++ ) {
$crc = $crc ^ ord( $string[$x] );
for ($y = 0; $y < 8; $y++) {
if ( ($crc & 0x0001) == 0x0001 ) $crc = ( ($crc >> 1 ) ^ 0xA001 );
else $crc = $crc >> 1;
}
}
return $crc;
}
答案 2 :(得分:0)
此代码每次都有效,但我并不完全了解正在发生的事情。
char *MakeCRC(char *BitString)
{
static char Res[17]; // CRC Result
char CRC[16];
int i;
char DoInvert;
for (i=0; i<16; ++i) CRC[i] = 0; // Init before calculation
for (i=0; i<strlen(BitString); ++i)
{
DoInvert = ('1'==BitString[i]) ^ CRC[15]; // XOR required?
CRC[15] = CRC[14];
CRC[14] = CRC[13];
CRC[13] = CRC[12];
CRC[12] = CRC[11];
CRC[11] = CRC[10];
CRC[10] = CRC[9] ^ DoInvert;
CRC[9] = CRC[8];
CRC[8] = CRC[7] ^ DoInvert;
CRC[7] = CRC[6] ^ DoInvert;
CRC[6] = CRC[5];
CRC[5] = CRC[4];
CRC[4] = CRC[3];
CRC[3] = CRC[2] ^ DoInvert;
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = DoInvert;
}
for (i=0; i<16; ++i) Res[15-i] = CRC[i] ? '1' : '0'; // Convert binary to ASCII
Res[16] = 0; // Set string terminator
return(Res);
}
// A simple test driver:
#include <stdio.h>
int main()
{
char *Data, *Result; // Declare two strings
Data = "1101000101000111";
Result = MakeCRC(Data); // Calculate CRC
printf("CRC of [%s] is [%s] with P=[10000010110001001]\n", Data, Result);
return(0);
}