2017-04-14 126 views
0

我想在c中創建一個CRC-15檢查,並且輸出永遠不會對文件的每一行都正確。我試圖在每行旁邊累積地輸出每行的CRC。我使用#define POLYNOMIAL 0xA053作爲除數和分紅文本。我需要將數字表示爲32位無符號整數。我試圖打印出十六進制值來跟蹤和翻轉不同的轉變。但是,我似乎無法弄清楚!我有一種感覺,它與我填充東西的方式有關。我的邏輯有缺陷嗎?CRC-15給出錯誤的值

CRC將以四個十六進制數字表示,該序列將具有四個前導0。例如,它看起來像0000xxxx,其中x是十六進制數字。我使用的多項式是0xA053。

我想過使用一個臨時變量,並且每個XOR每行都執行4個16位塊的代碼,但是,我不太確定如何使用班次來完成這個操作,所以我解決了字母校驗和問題該行然後異或以嘗試計算CRC碼。

我正在測試我的代碼,使用下面的輸入和填充。直到字符串的長度爲504,因爲這是墊字符需要通過給定的要求: 「這是一個教訓:永不放棄,永不放棄,永不永遠,永不絕望,絕不 - 永遠 - 沒有,偉大的或小的,大的或小的 - 除了要有榮譽和良好的判斷力外,絕不要屈服,絕不屈服於力量,絕不屈服於敵人的壓倒性力量。「

第64字符行的CRC(「這是教訓:永遠不要放棄,永不放棄,永遠,永遠,)應該是000015fa和我得到bfe6ec00

我的邏輯:

  • 在CRCCalculation我每個字符添加到一個32位無符號整數,64(一條線的長度)後,我將其發送到XOR函數。

  • 如果最高位是不1,我把號碼移到左邊的那個 ca使用0填充右邊並再次循環。

  • 如果最高位是1,我將除數與除數異或,然後將除數轉移到左邊。

  • 所有的計算都完成後,我回到了紅利轉移到了左四(四個零的前面加)的計算功能

  • 添加結果到正在運行的總結果的

代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdint.h> 
#include <ctype.h> 
#define POLYNOMIAL 0xA053 
void crcCalculation(char *text, int length) 
{ 
    int i; 
    uint32_t dividend = atoi(text); 
    uint32_t result; 
    uint32_t sumText = 0; 

    // Calculate CRC 
    printf("\nCRC 15 calculation progress:\n"); 

    i = length; 

    // padding 
    if(i < 504) 
     { 
      for(; i!=504; i++) 
       { 
        // printf("i is %d\n", i); 
        text[i] = '.'; 
       } 
     } 
    // Try calculating by first line of crc by summing the values then calcuating, then add in the next line 
    for (i = 0; i < 504; i++) 
     { 
      if(i%64 == 0 && i != 0) 
       { 
        result = XOR(POLYNOMIAL, sumText); 
        printf(" - %x\n",result); 


       } 
      sumText +=(uint32_t)text[i]; 
      printf("%c", text[i]); 
     } 

    printf("\n\nCRC15 result : %x\n", result); 
} 

uint32_t XOR(uint32_t divisor, uint32_t dividend) 
{ 
    uint32_t divRemainder = dividend; 
    uint32_t currentBit; 
    // Note: 4 16 bit chunks 

    for(currentBit = 32; currentBit > 0; --currentBit) 
     { 
      // if topbit is 1 
      if(divRemainder & 0x80) 
       { 
        //divRemainder = (divRemainder << 1)^divisor; 
        divRemainder ^= divisor; 
        printf("%x %x\n", divRemainder, divisor); 
       } 
      // else 
      // divisor = divisor >> 1; 
      divRemainder = (divRemainder << 1); 
     } 
    //return divRemainder; , have tried shifting to right and left, want to add 4 zeros to front so >> 
    //return divRemainder >> 4; 
    return divRemainder >> 4; 
} 
+0

你爲什麼總結每個64個字符的文字?這不是一個CRC。 – TrentP

+0

我試圖獲得每條線的CRC總數cummatively,我認爲這個總結和XORing會得到該行的位,然後我會去並添加在下一行,並獲得這些位...我是考慮將文本數組發送到XOR函數中,並創建一個臨時變量來逐位移位,但是,我不太清楚如何將這些位移入臨時數組。例如,如果我發送一行4個16位塊進入異或,並根據需要移入另一位,直到數組爲空,並將其用於異或事情,這會比求和更多的CRC嗎? – starlight

+0

爲什麼你不計算16位CRC?每次使用一個完整的字節要容易得多,而不是部分字節/ – user3629249

回答

1

第一個問題,我看到的是頂位檢查,它應該是:

 if(divRemainder & 0x8000) 

如果CRC比特反射(XOR數據轉換成CRC的低位比特,用於循環向右移位)或未被(XOR數據轉換成CRC的高位比特,用於循環左移位)的問題沒有說明,所以我無法爲其餘的代碼提供幫助。

這個問題沒有說明CRC的初始值(0x0000或0x7fff),或者CRC是後綴補充的。

用於常規CRC的邏輯是:

  • XOR數據的一個字節到CRC(上或下位)
  • 循環的CRC的8倍(或執行表查找)

在爲整個消息生成CRC後,可以將CRC附加到消息中。如果爲具有附加CRC的消息生成CRC並且沒有錯誤,則CRC將爲零(或者如果CRC被後補充,則爲恆定值)。

+0

我不太清楚CRC的初始值是什麼意思,我設置結果= 0,然後將xor值加和到結果中。至於反映,我正在更新這篇文章,希望能回答這個問題。 – starlight

+0

@starlight - 我更新了我的答案。 – rcgldr

1

這裏是一個典型的CRC16,從提取:<www8.cs.umu.se/~isak/snippets/crc-16.c>

#define POLY 0x8408 
/* 
//          16 12 5 
// this is the CCITT CRC 16 polynomial X + X + X + 1. 
// This works out to be 0x1021, but the way the algorithm works 
// lets us use 0x8408 (the reverse of the bit pattern). The high 
// bit is always assumed to be set, thus we only use 16 bits to 
// represent the 17 bit value. 
*/ 

unsigned short crc16(char *data_p, unsigned short length) 
{ 
     unsigned char i; 
     unsigned int data; 
     unsigned int crc = 0xffff; 

     if (length == 0) 
      return (~crc); 

     do 
     { 
      for (i=0, data=(unsigned int)0xff & *data_p++; 
       i < 8; 
       i++, data >>= 1) 
      { 
        if ((crc & 0x0001)^(data & 0x0001)) 
         crc = (crc >> 1)^POLY; 
        else crc >>= 1; 
      } 
     } while (--length); 

     crc = ~crc; 
     data = crc; 
     crc = (crc << 8) | (data >> 8 & 0xff); 

     return (crc); 
} 

由於要計算CRC15,而不是一個CRC16,邏輯會更復雜,因爲不能全部字節工作,所以會有很多位移和AND操作來提取慾望15位。

注意:OP沒有提及CRC的初始值是0x0000還是0x7FFF,結果是補全還是其他條件,所以本發佈代碼只能作爲指導。

+0

應該注意的是,預先計算CRC表可以使該代碼更快得多,因爲可以消除內部循環和位移。 – user3629249

+0

謝謝!我會研究一下。 – starlight