CRC 16 -DECT con poli x ^ 16 + x ^ 10 + x ^ 8 + x ^ 7 + x ^ 3 + 1
Domanda
credetemi ho cercato di codice di questo, ha cercato di Google, e non ho avuto fortuna. Sto cercando di implementare un CRC16 utilizzando questo poli
x^16 + x^10 + x^8 + x^7 + x^3 + 1
utilizzando il linguaggio C. Dal momento che ho capito meglio PHP sto cercando di ottenere una funzione in corso, ma non sto ricevendo la risposta giusta di 28713. Questo codice genera un CRC di 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');
mi permetto a nessuno di dare una mano con this..thanks in anticipo.
Soluzione
-
Alcuni CRC sono definiti per elaborare i bit di ciascun byte dal MSB a LSB, e alcuni sono definiti ai bit di processo da LSB al MSB (quest'ultimo è generalmente l'ordine che viene descritta come "riflessi" e usano un invertito polinomiale). I vostri mette nuovo codice bit a LSB fine della CRC e si sposta verso destra, che è adatto per un CRC riflessa, ma CRC-16-DECT sembra essere uno di quelli non-riflesso.
-
L'ingresso di "10100011" suggerisce binario, ma viene elaborato come una stringa ASCII di 8 byte.
Per vedere cosa succede quando si trattano 10.100.011 come binario invece, e di lavoro da MSB prima, ecco un calcolo a mano (come 8 bit di ingresso non richiede molto sforzo):
polynomial coefficients
|
| 10100010 <--- quotient (irrelevant)
v __________
10000010110001001 ) 10100011 <-------- input
^ 10000010110001001
-----------------
= 100001110001001
^ 10000010110001001
-----------------
= 101110101101
^ 10000010110001001
-----------------
remainder (CRC) -----> = 111000000101001
= 0x7029 = 28713
Quindi, trattando l'ingresso come binario e MSB lavorando prima è la cosa giusta da fare.
Ecco il codice C per fare il lavoro (come io non sono davvero in PHP, e in ultima analisi si voglia codice C in ogni caso):
#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;
}
Risultato:
$ gcc -Wall -o crc16 crc16.c
$ ./crc16
28713 (0x7029)
$
Altri suggerimenti
Provare a cambiare 0x10589 a 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;
}
Questo codice funziona ogni volta, ma io non sono esattamente capire cosa sta succedendo.
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);
}