2016-05-07 65 views
1

我有一个Athena 16C控制器,我通过RS232进行控制。它的消息协议需要专有校验和:如何编码/解码此专有校验和(雅典娜16C PID控制器)?

“CHKSUM:这是一个双字符消息代码编号系统,表示所有字符的所有ASCII值的总和(不包括START,CHAR,END CHAR和CHKSM自己)在邮件中,总和计算公式如下: CHKSM = SUM(所有邮件字符)%256其中%表示模数运算符。

示例消息(从他们的文档)是这样的:

$Ø1Ø1RØ5C1<CR> 

和可细分为:

$ [START CHAR] 01 [ID] 01 [ZONE] R [TYPE] 05 [PARAM] C1 [CHKSM] <CR> [END CHAR] 

我已将这个消息给控制器,它按预期工作。 “C1”根据消息格式

var sum = 'Ø1Ø1RØ5' 
    .split('') 
    .map(function(char) { 
     return char.charCodeAt(0); 
    }) 
    .reduce(function(current, previous) { 
     return previous + current; 
    }); 

var chksm = (sum % 256); 
console.log(chksm.toString(16)); 

校验应该是:

我写我的JS代码,并且是应该计算CHKSM把在邮件的末尾以下。但是计算的总和是377,这导致121的校验和等于十六进制的79。

// 0 = 48, 1 = 49, R = 82, 5 = 53 (ASCII values) 
// 48 + 49 + 48 + 49 + 82 + 48 + 53 = 377 
// 377 % 256 = 121 (decimal) = 79 (hex) 

雅典娜的一位工程师寄给我下面的VB代码,但我无法理解逻辑,也没有特别的语法。总的来说,这个问题有什么基础?

' Covert the mod % 256 checksum to the 2 chars: 
' Will set First and Second chars for encoded value. Pass in the value (Checksum mod 256) 
' and where to return the 1st and 2nd chars to. 
Public Sub EncodeIt(ByVal Value As Integer, ByRef FirstChar As Integer, ByRef SecondChar As Integer) 

    If Value > 359 Then 'Z9 = 359, absolute max possible 
     Value = 359 
    End If 

    'Note: backslash '\' means integer divide, not floating point!! 
    If Value > 99 Then 
     FirstChar = (Value \ 10) + 65 - 10 '65 = ascii "A" 
    Else 
     FirstChar = (Value \ 10) + 48   '48 = ascii "0" 
    End If 

    SecondChar = (Value Mod 10) + 48 

End Sub 

' Convert the two chars received in a message back to normal integer. 
' Take the 2 chars and return a decoded integer value 
Public Function DecodeIt(ByVal FirstChar As Integer, ByVal SecondChar As Integer) As Integer 

    '65 = ascii "A", 48 = ascii "0" 
    If FirstChar > 57 Then '57 = ascii "9" 
     Return ((FirstChar - 65 + 10) * 10) + (SecondChar - 48) 
    Else 
     Return ((FirstChar - 48) * 10) + (SecondChar - 48) 

    End If 

End Function 

回答

1

从十进制到字符串的编码是cutom而不是base16。这就是为什么(121).toString(16)不等于C1。 从您的文章的VBA编码/解码功能应该是:

function compute_checksum(message) { 
    var sum = 0; 
    for(var i=0; i<message.length; i++) 
     sum += message.charCodeAt(i); 
    return sum % 256; 
} 

function encode_checksum(value) { 
    value = Math.min(value, 359); 
    var c1 = ((value/10) | 0) + (value > 99 ? 55 : 48); 
    var c2 = (value % 10) + 48; 
    return String.fromCharCode(c1, c2); 
} 

function decode_checksum(text) { 
    var c1 = text.charCodeAt(0); 
    var c2 = text.charCodeAt(1); 
    return (c1 > 57 ? c1 - 55 : c1 - 48) * 10 + (c2 - 48) 
} 

下面是一个使用示例:

var checksum = compute_checksum('0101R05'); 
console.log('checksum: ' + checksum); 

var CHKSM = encode_checksum(checksum); 
console.log('encoded checksum: ' + CHKSM); 
console.log('decoded checksum: ' + decode_checksum(CHKSM)); 
1

我只是通过这个去了C#和与上面的帮助下,来到(适用于我): 'reqtemp'是包含控制器ID#,Zone,参数等的字符串,不包含开始和校验和字符。

// generate checksum for Athena 
      int x = 0; 
      int sl = reqtemp.Length; 
      int FirstChar = 0; //checksum 1st character 
      int SecondChar = 0; //checksum 2nd char 

      string crcr; // crc for requests 

      for (int c = 0; c < sl; c++) 
      { 
       string sel = reqtemp.Substring(c, 1); 

       x = x + Convert.ToChar(sel); 
      } 
      x = x % 256; //modular 256 
      x = Math.Min(x, 359); // don't allow > 359 
      if (x > 99) 
      { FirstChar = (x/10) + 65 - 10; } 
      else 
      { FirstChar = (x/10) + 48; } 

      SecondChar = (x % 10) + 48; 

      crcr = Char.ConvertFromUtf32(FirstChar) + Char.ConvertFromUtf32(SecondChar); 
      //  MessageBox.Show(crcr); 


      string reqtempfull = "$"+ reqtemp + crcr + (char)13; 
      crc.Text = reqtempfull; //display the full sp string 
      if (ComPort.IsOpen) 
      { 
       ComPort.Write(reqtempfull); // send it`enter code here` 
      }