2016-04-28 10 views
1

Ich habe folgende Protokoll-Spezifikation für Nachrichten an ein Gerät zu senden, mit denen uns der Integration in Bytes unterteilt, die durch Bestellung:Probleme mit Prüfsumme Bits auf einem benutzerdefiniertes Protokoll in Ruby Implementierung

  1. Binary 0x02
  2. Startbyte
  3. ASCII '1' oder '2' oder '3' bzw. '4' Geräteadresse
  4. ASCII '0' - Keine Änderung '1' - Change Ausgang Lastausgangsänderung
  5. ASCII 'E' - Boost-Spannung Set ' D '- Entladespannung' T '- Temperaturkompensation' C '- Max.
  6. ASCII '0' - Keine Änderung '-' - Ausgewählte Wert herunterschalten '+'
  7. Binary s = (Byte) SUM (2; 5) CRC_H = 0b1000_s7_s6_s5_s4 Checksum Höhe Byte
  8. Binary s = (byte) SUM (2; 5) = CRC_L 0b1000_s3_s2_s1_s0 Checksum low byte
  9. Binary 0x03

ich habe Probleme bekommen Bytes 6 & 7 korrekt.

Es ist nicht sehr klar, wie man die Prüfsumme berechnet, es sagt Byte 6 und 7 sind eine Summe von (2; 5) - was bedeutet 2; 5?

der Code i haben derzeit ist:

require 'serialport' 

# Open collector serial port 
serial = SerialPort.new('/dev/ttyAMA0', baud: 9600, data_bits: 8, stop_bits: 1, 
    parity: SerialPort::NONE) 

checksum = '10E0'.unpack("C*").inject(:+).ord 
p serial.write(0x02.chr) # start byte 
p serial.write('10E0') # commands 
p serial.write(checksum + checksum) # checksum byte 1 + 2 
p serial.write(0x03.chr) # End byte 
p serial.read 

kein Glück mit einer Antwort. Hat jemand eine Idee, was mache ich falsch? oder ein besseres Verständnis für diese Spezifikation?

Vielen Dank!

+0

Nehmen Sie zwei Aspirin und dann einen Blick auf [Array # pack] (http://ruby-doc.org/core-2.2.0/Array.html#method-i-pack) und [String #unpack] (http://ruby-doc.org/core-2.2.0/String.html#method-i-unpack). –

+0

Vielen Dank dafür, wie würde ich die 1101 und 0110 als ein einzelnes Byte schreiben? - Ich habe versucht, 1101.ord, aber das sagt 'chr ': 1101 außerhalb Char Bereich (RangeError) –

+0

Sorry, ich habe einen Fehler in meinem ursprünglichen Kommentar, so dass ich es gelöscht und eine korrigierte Version unten hinzufügen. Ich bin nicht mit 'SerialPort' vertraut, also müssen Sie die Dokumente überprüfen, um zu sehen, wie man die Bytes' 0x0' und '0xD6' schreibt. –

Antwort

2

Ihre "Protokollspezifikation" ist verwirrend. Für Bytes 6 & 7 erwähnt es sowohl "Prüfsumme" und "CRC". Das sind zwei verschiedene Arten von Berechnungen. Sie sind auch nicht. Checksum ist anfällig für falsche Validierungen bei mehreren Bitfehlern. CRC ist viel besser darin, Fehler zu erkennen.

Sie müssen also die Frage beantworten, ob Sie den CRC-8-Prüfwert oder die auf ein Byte gekürzte Prüfsumme der Nachrichtenbytes 2 bis 5 berechnen müssen. Unabhängig davon würden Sie einen 8-Bit-Wert erhalten in Nachricht gespeichert werden Bytes 6 & 7.

Ihre "protocol spec" hat:

6. Binary s=(byte)SUM(2;5) CRC_H=0b1000_s7_s6_s5_s4 Checksum hight byte 
7. Binary s=(byte)SUM(2;5) CRC_L=0b1000_s3_s2_s1_s0 Checksum low byte 

Offenbar wird die hohe Halbbyte des Prüfsummen-Byte (dh Bits "s7_s6_s5_s4"), gespeichert in Byte 6 der Nachricht mit dem High Bit (Bit 8) gesetzt (wie durch die "0b1000_" Bitfolge angezeigt). Das Low-Nibble des Prüfsummenbytes (d. H. Bits "s3_s2_s1_s0") ist in Byte 7 der Nachricht gespeichert, wobei das High-Bit (Bit 8) gesetzt ist.

Vermutlich wird durch Setzen von Bit 8 (in jedem Byte) eine falsche Erkennung des Start- oder Endbytes der Nachricht verhindert, wenn die Prüfsumme den Wert 0x02 oder 0x03 ergibt. Dies sollte die Nachrichtenintegrität verbessern, indem der Nachrichtenrahmen leicht zu identifizieren und schwer zu identifizieren ist.

Ich mache keinen Ruby, kann also nur C-Code anbieten.

unsigned char chksum = mesg[2] + mesg[3] + mesg[4] + mesg[5]; 
mesg[6] = 0x80 | ((chksum >> 4) & 0x0f); 
mesg[7] = 0x80 | (chksum & 0x0f);