2014-06-08 7 views
5

HintergrundPerl pack() ing eine Nachricht?

Ich habe ein Gerät an einer seriellen Schnittstelle an meine Maschine verbunden, die Nachricht ausgerichtet ist, wobei jede eingehende Befehlsnachricht genau acht Worte 16-Bit ist. Das höchstwertige Byte jedes Wortes wird zuerst empfangen und das niedrigstwertige Byte wird als zweites empfangen. Jedes Kopfzeilenwort ist eine Befehlskennung (von 0 bis 255). Das Format ist wie so definiert:

XXXX Header Word (Placeholder for 16-bit Hexadecimal value) 
XXXX Data Word 
XXXX Data Word 
XXXX Data Word 
XXXX Data Word 
XXXX Data Word 
XXXX Data Word 
XXXX Checksum Word (Result of Exclusive OR on header word and all six data words) 

Das Format für den Befehl, den ich senden müssen, header 0x5D, wie so definiert:

Word 1: Header = 005Dh 
Word 2: Mode (values can be 2, 3, 6, 8, 9) 
Words 3-7: Not significant 
Word 8: 16 bit checksum 

Fragen (alle bezogen)

Ich habe dieses Beispiel aus anderem Quellcode, der diese Nachricht scheinbar korrekt sendet, aber ich bin mir nicht sicher, was vor sich geht, auch nach dem Lesen von perldoc auf dem Paket.

pack("v"x8, 0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D); 
  1. "v" bedeutet, Little-Endian, aber ich kann keinen Hinweis auf die x8 folgenden es finden.
  2. Und nach dem Format der Nachricht, sollte nicht der 0x5D Wert nach dem "v" x8, nicht nach dem 0x00 sein?
  3. Die Nachricht soll acht 16-Bit-Wörter haben, also warum gibt es 16 und nicht 8? Einige sind 0x00 und nicht 0x0? Macht das einen Unterschied?
+1

nicht ' "v" x8' bedeutet' vvvvvvvv'? – Fabricator

+0

Ah, richtig. Die Zeichenfolge, die Multiplikatormagie wiederholt. Nicht im Zusammenhang mit Pack sondern Saiten im Allgemeinen. Also wurde es nur knapp geschrieben anstatt "pack" ("vvvvvvvv", ....). Immer noch auf Fragen 2 und 3 verloren. – rem45acp

+0

Auf welchen "0x68-Wert" beziehen Sie sich in Frage 2? Es gibt keinen 0x68-Wert in der angegebenen Spezifikation oder im Code. – jwodder

Antwort

5

pack "v"x8 (die in pack "vvvvvvvv" führt, die als pack "v8" kurz geschrieben werden können) packt acht 16-Bit-Zahlen, aber Sie sechzehn weitergegeben.

Wenn Sie sechzehn Bytes bereits haben, möchten Sie

pack 'C16', 0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D 

Aber ich würde erwarten, dass Sie acht Wörter 16-Bit statt haben, so würden Sie

pack 'n8', 0x005D, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x005D 

Beachten Sie die Verwendung von verwenden n anstelle von v, um die gewünschte Byte-Reihenfolge zu erhalten.

pack 'v', 0x1234  => "\x34\x12" Most significant byte last 
pack 'n', 0x1234  => "\x12\x34" Most significant byte first 

Der Nachweis, dass beide Methoden gleichwertig sind:

my $method1 = pack 'C16', 
    0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D; 

my $method2 = pack 'n8', 
    0x005D, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x005D; 

print($method1 eq $method2 ? "yes" : "no", "\n"); # yes 
+1

Diese Antwort ist sehr sinnvoll.Das "v8", das ich im Perl doc, aber nicht im "v" x8 gesehen habe, hat nicht erkannt, dass sie gleich sind. Aber sechzehn Werte oder acht Werte zu übergeben, ist im Grunde die gleiche Eingabe, oder? Solange jeder 16-Bit ist. Ich finde 8 klarer, da die Nachricht so definiert wurde, dass sie die acht 16-Bit-Wörter enthält, und es zeigt, dass das erste Wort tatsächlich den Nachrichtenkopf hat. Ich werde mit der Byte-Reihenfolge experimentieren müssen. – rem45acp

+0

Re "Aber sechzehn Werte oder acht Werte zu übergeben, ist im Grunde die gleiche Eingabe, richtig?" Wie ich gezeigt habe, können Sie die gleichen gepackten Daten aus 16 Zahlen oder 8 Zahlen konstruieren, aber diese Zahlen müssen anders sein, und auch die Anweisungen, wie sie zu packen sind. Ich habe Beweise hinzugefügt, dass beide Methoden gleichwertig sind. – ikegami