CRC 16 -dect with poly x^16 + x^10 + x^8 + x^7 + x^3 + 1
質問
私はこれをコーディングしようとし、Googleを試してみましたが、運がありませんでした。このポリを使用してCRC16を実装しようとしています
x^16 + x^10 + x^8 + x^7 + x^3 + 1
C言語を使用します。私はPHPをよりよく理解しているので、私は関数を動かしようとしていますが、28713の正しい答えは得られていません。このコードは32713のCRCを生成しています。
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');
事前にありがとう。
解決
一部のCRCは、各バイトからMSBからLSBへのビットを処理するために定義され、一部はLSBからMSBにビットを処理するために定義されます(後者は一般に「反射」と記述され、反転した多項式を使用する順序です)。コードはCRCのLSB端に新しいビットを入れ、反射CRCに適していますが、CRC-16-DECTはリフルスされていないものの1つであるように見えます。
「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
したがって、入力をバイナリとして扱い、最初に動作することは正しいことです。
ジョブを行うためのいくつかの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)
$
他のヒント
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;
}
このコードは毎回動作しますが、何が起こっているのかを正確に理解していません。
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);
}
所属していません StackOverflow