سؤال

صدقوني لقد حاولت ترميز هذا ، وجربت Google ، ولم أحصل على أي حظ. أحاول تنفيذ CRC16 باستخدام هذا بولي

x^16 + x^10 + x^8 + x^7 + x^3 + 1

باستخدام لغة C. نظرًا لأنني أفهم بشكل أفضل ، فأنا أحاول الحصول على وظيفة ، لكنني لا أحصل على الإجابة الصحيحة لـ 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');

من فضلك أتوسل إلى أي شخص أن يعطي يده مع هذا .. شكرا مقدما.

هل كانت مفيدة؟

المحلول

  1. يتم تعريف بعض CRCs لمعالجة البتات من كل بايت من MSB إلى LSB ، ويتم تعريف بعضها لمعالجة البتات من LSB إلى MSB (يكون الأخير هو الترتيب الذي يوصف على أنه "انعكاس" ويستخدم متعدد الحدود العكسي). يضع الكود الخاص بك أجزاء جديدة في نهاية LSB من CRC ويتحول إلى اليمين ، وهو مناسب لاتفاقية حقوق الطفل المنعكسة ، ولكن يبدو أن CRC-16-DECT هي واحدة من تلك غير المنعكسة.

  2. تقترح مدخلاتك من "10100011" ثنائية ، ولكن تتم معالجتها كسلسلة ASCII 8 بايت.

لمعرفة ما يحدث عند التعامل مع 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)
$ 

نصائح أخرى

حاول تغيير 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);
      }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top