2014-09-19 153 views
0

我試圖實現16-CRC [DNP]使用C#中,generator polynomial給出如何使用C#實現CRC-16-DNP?

enter image description here

我發現16-CRC的標準溶液:[Source]

public class Crc16 
{ 
    const ushort polynomial = 0xA001; 
    ushort[] table = new ushort[256]; 

    public ushort ComputeChecksum (byte[] bytes) 
    { 
     ushort crc = 0; 
     for (int i = 0; i < bytes.Length; ++i) 
     { 
      byte index = (byte) (crc^bytes[i]); 
      crc = (ushort) ((crc >> 8)^table[index]); 
     } 
     return crc; 
    } 

    public byte[] ComputeChecksumBytes (byte[] bytes) 
    { 
     ushort crc = ComputeChecksum (bytes); 
     return BitConverter.GetBytes (crc); 
    } 

    public Crc16() 
    { 
     ushort value; 
     ushort temp; 
     for (ushort i = 0; i < table.Length; ++i) 
     { 
      value = 0; 
      temp = i; 
      for (byte j = 0; j < 8; ++j) 
      { 
       if (((value^temp) & 0x0001) != 0) 
       { 
        value = (ushort) ((value >> 1)^polynomial); 
       } 
       else 
       { 
        value >>= 1; 
       } 
       temp >>= 1; 
      } 
      table[i] = value; 
     } 
    } 
} 

現在,如果我轉換我的多項式我得到1 0011 1101 0110 0111 =>(3D65)h &我的問題是我需要改變爲給定多項式的上述解決方案。

Edit:我還需要考慮兩件事情,

1)初始值爲0 &
2)最後的CRC必須加以補充。

回答

0

最後,我結束了使用以下解決方案&認爲它值得分享&它可能對某人有用。

private static int GetCrc (string BitString) 
    { 
     bool[] Res = new bool[17]; 
     bool[] CRC = new bool[16]; 
     int i; 
     bool DoInvert = false; 
     string crcBits = string.Empty; 

     for (i = 0; i < 16; ++i) // Init before calculation 
      CRC[i] = false; 

     for (i = 0; i < BitString.Length; ++i) 
     { 
      DoInvert = ('1' == BitString[i])^CRC[15]; // XOR required? 

      CRC[15] = CRC[14]; 
      CRC[14] = CRC[13]; 
      CRC[13] = CRC[12]^DoInvert; 
      CRC[12] = CRC[11]^DoInvert; 
      CRC[11] = CRC[10]^DoInvert; 
      CRC[10] = CRC[9]^DoInvert; 
      CRC[9] = CRC[8]; 
      CRC[8] = CRC[7]^DoInvert; 
      CRC[7] = CRC[6]; 
      CRC[6] = CRC[5]^DoInvert; 
      CRC[5] = CRC[4]^DoInvert; 
      CRC[4] = CRC[3]; 
      CRC[3] = CRC[2]; 
      CRC[2] = CRC[1]^DoInvert; 
      CRC[1] = CRC[0]; 
      CRC[0] = DoInvert; 
     } 

     for (i = 0; i < 16; ++i) 
      Res[15 - i] = CRC[i] ? true : false; 

     Res[16] = false; 

     // The final result must be Complemented    
     for (i = 0; i < 16; i++) 
     { 
      if (Res[i]) 
       crcBits += "0"; 
      else 
       crcBits += "1"; 
     } 

     return Convert.ToInt32 (crcBits, 2); 
    } 

上述C#溶液從C based auto generated codehere轉換。

2

第一個鏈接的代碼有什麼問題?這也指定了如何在消息中排序CRC字節。

您需要反轉以下的多項式x 。位形式的多項式是10011110101100101。刪除前導1(x ),並且您有四個組:0011 1101 0110 0101。相反的是:1010 0110 1011 1100。所以你應該設置polynomial = 0xA6BC

初始值已經爲零。完成最終的CRC可以簡單地用^ 0xffff完成。

+0

對不起,我以前沒有清楚,請參閱上面的編輯部分,也請你解釋你是如何得到'0XA6BC'? – SanVEE 2014-09-19 16:07:36

1

這實際上對我非常有幫助。但是,我沒有使用SanVEE所做的解決方案,我實際上按照Mark Adler的描述修改了他原來的帖子中的代碼,並且效果很好。至少,到目前爲止,結果與在此處找到的DNP3校驗和計算器相匹配:http://www.lammertbies.nl/comm/info/crc-calculation.html

作爲SanVEE的答案發布的代碼看起來可能非常低效(例如,使用bools存儲每一位),儘管我有沒有測試他們進行比較。任何面臨相同問題的人都可能想要檢查兩個答案,以查看哪些更適合他們。

public class Crc16DNP3 
    { 
     const ushort polynomial = 0xA6BC; //0xA001; 
     ushort[] table = new ushort[256]; 

     public ushort ComputeChecksum(byte[] bytes) 
     { 
      ushort crc = 0; 
      for (int i = 0; i < bytes.Length; ++i) 
      { 
       byte index = (byte)(crc^bytes[i]); 
       crc = (ushort)((crc >> 8)^table[index]); 
      } 
      crc = SwapBytes((ushort)(crc^0xffff)); 
      return crc; 
     } 

     public byte[] ComputeChecksumBytes(byte[] bytes) 
     { 
      ushort crc = ComputeChecksum(bytes); 
      return BitConverter.GetBytes(crc); 
     } 

     // SwapBytes taken from http://stackoverflow.com/questions/19560436/bitwise-endian-swap-for-various-types 
     private ushort SwapBytes(ushort x) 
     { 
      return (ushort)((ushort)((x & 0xff) << 8) | ((x >> 8) & 0xff)); 
     } 

     public Crc16DNP3() 
     { 
      ushort value; 
      ushort temp; 
      for (ushort i = 0; i < table.Length; ++i) 
      { 
       value = 0; 
       temp = i; 
       for (byte j = 0; j < 8; ++j) 
       { 
        if (((value^temp) & 0x0001) != 0) 
        { 
         value = (ushort)((value >> 1)^polynomial); 
        } 
        else 
        { 
         value >>= 1; 
        } 
        temp >>= 1; 
       } 
       table[i] = value; 
      } 
     } 
    } 
+0

非常感謝 – JohnLaird 2016-09-02 16:00:40