2016-05-07 1 views
1

У меня есть контроллер Athena 16C, который я контролирую через RS232. Для протокола обмена сообщениями требуется контрольная сумма:Как я могу кодировать/декодировать эту проприетарную контрольную сумму (PID-контроллер Athena 16C)?

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] 

Я послал это сообщение к контроллеру, и он работает, как ожидалось.

Я пишу свой код в JS и иметь следующий, который, как предполагается рассчитать CHKSM поставить в конце сообщения:

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)); 

Контрольная сумма должна быть «C1» в соответствии с форматом сообщения , Но рассчитанная сумма равна 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) 

Инженер из Athena прислал мне следующий код 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

Кодировка от десятичной до строчки - это сделанный кубик, а не основание16. Вот почему (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 контроллера, зону, параметр и т. д. без символов начала и контрольной суммы.

// 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` 
      } 
Смежные вопросы