2014-09-24 25 views
3

我正在使用一個嵌入式系統,該系統返回包含(我相信是)的ASCII數據。我想驗證這個校驗和,但是我根據製造商的規格一直無法這樣做。我也無法完成相反的操作,並根據描述計算相同的校驗和。在c中驗證模塊化總和校驗和#

從器件中的每個響應是以下格式:

╔═════╦═══════════════╦════════════╦════╦══════════╦═════╗ 
║ SOH ║ Function Code ║ Data Field ║ && ║ Checksum ║ ETX ║ 
╚═════╩═══════════════╩════════════╩════╩══════════╩═════╝ 

實施例:

SOHi11A0014092414220&&FBEA 

哪裏SOH是ASCII 1例如

#define SOH "\x01" 

校驗和的說明如下:

校驗和是一系列四個ASCII十六進制字符,其提供上的所有字符的完整的檢查它之前,包括控制 個字符。這四個字符表示一個16位二進制計數,它是奇偶校驗位(如果使能)被清除後,消息字符的8位二進制表示的二進制補碼總和。溢出被忽略。數據完整性檢查可以通過將四個校驗和字符轉換爲16位的 二進制數字並將消息字符的8位二進制表示添加到它來完成。二進制結果應該爲零。

我試過了一些對規範的不同解釋,包括忽略SOH以及和號,甚至函數代碼。 在這一點上,我必須在我對規範的解釋或我一直用來測試的代碼中忽略一些非常明顯的東西。下面你會發現一個簡單的例子(數據來自現場系統獲取),如果它是正確的,在驗證變量的低位字是0

static void Main(string[] args) 
{ 
    unchecked 
    { 
     var data = String.Format("{0}{1}", (char) 1, @"i11A0014092414220&&"); 
     const string checkSum = "FBEA"; 

     // Checksum is 16 bit word 
     var checkSumValue = Convert.ToUInt16(checkSum, 16); 

     // Sum of message chars preceeding checksum 
     var mySum = data.TakeWhile(c => c != '&').Aggregate(0, (current, c) => current + c); 
     var validate = checkSumValue + mySum; 

     Console.WriteLine("Data: {0}", data); 
     Console.WriteLine("Checksum: {0:X4}", checkSumValue); 
     Console.WriteLine("Sum of chars: {0:X4}", mySum); 
     Console.WriteLine("Validation: {0}", Convert.ToString(validate, 2)); 
     Console.ReadKey(); 
    } 
} 

編輯

雖然通過爲這個特定的例子@tinstaafl工作所提供的解決方案,提供更大的記錄時,它不起作用,如下面的:

SOHi20100140924165011000007460904004608B40045361000427DDD6300000000427C3C66000000002200000745B41000 45B3D8004508C00042754B900000000042774D8D0000000033000007453240004531E000459F5000420EA4E100000000427B14BB000000005500000744E0200044DF4000454AE000421318A0000000004288A998000000006600000744E8C00044E7200045469000421753E600000000428B4DA50000000 & &

BA6C 

理論上你可以不斷遞增/遞減字符串中的值,直到校驗和匹配,它只是碰巧使用字符1,而不是ASCII SOH控制字符給它恰到好處的價值,在這種情況下是巧合。

+0

功能代碼/數據字段的長度是否固定? 是否有任何ASCII控制字符分隔輸入? 第二個例子是SOH的主要部分,還是功能代碼的開始? – user1112560 2014-09-25 00:20:45

+0

功能代碼的長度似乎是固定的,數據字段的長度取決於功能代碼。有些還具有可變數量的固定列。我編輯了這個示例,並刪除了在消息開頭的那個1,並用SOH替換了它。我在那裏說明,用1代替SOH只是第一個例子中的巧合。 – dpeterson 2014-09-25 13:18:10

+0

我強烈懷疑規格不完整或出現錯誤。 8位無符號二進制的最大值是255. 2的補碼應該是負值。然而,校驗和值小於-255,因此當添加到校驗和值時,丟棄溢出的8位總和永遠不會等於0. – tinstaafl 2014-09-25 17:29:34

回答

1

不知道這是否正是您要查找的內容,而是通過使用SOH的整數1而不是1的char值,取所有字符的總和並將validate變量轉換爲16我能夠驗證等於0:

var data = (@"1i11A0014092414220&&"); 
const string checkSum = "FBEA"; 

// Checksum is 16 bit word 
var checkSumValue = Convert.ToUInt16(checkSum, 16); 

// Sum of message chars preceeding checksum 
var mySum = data.Sum<char>(c => c); 
var validate = (UInt16)(checkSumValue + mySum); 

Console.WriteLine("Data: {0}", data); 
Console.WriteLine("Checksum: {0:X4}", checkSumValue); 
Console.WriteLine("Sum of chars: {0:X4}", mySum); 

Console.WriteLine("Validation: {0}", Convert.ToString(validate, 2)); 
Console.ReadKey(); 
+0

不幸的是,似乎只適用於這個特殊的例子,這是這種校驗和的弱點之一。我將編輯我的問題以提供一個以1代替它不起作用的例子。 – dpeterson 2014-09-24 22:01:45