2017-01-30 6 views
0

Ich schreibe Code, die Nachrichten erstellen über einen CANBUS mit einem bestimmten Protokoll gesendet werden. Ein beispielhaftes Format für ein Datenfeld einer solchen Nachricht ist:Konvertieren von Binär in Bytearray mit 8-Bit-Codierung

[FROM_ADDRESS (1 Byte)] [control_byte (1 Byte)] [Identifikator (3 Byte)] [Länge (3 Byte)]

The Das Datenfeld muss als Liste oder Bytearray formatiert sein. Mein Code zur Zeit geschieht Folgendes:

data = dataFormat((from_address << 56)|(control_byte << 48)|(identifier << 24)|(length)) 

wo dataformat wie folgt definiert ist:

def dataFormat(num): 
    intermediary = BitArray(bin(num)) 
    return bytearray(intermediary.bytes) 

Dies tut genau das, was ich will es, außer wenn from_address eine Zahl, die in weniger beschrieben werden kann als 8 Bits. In diesen Fällen bin() einen binäre von Zeichenlänge nicht durch 8 teilbar (Fremd Nullen werden verworfen) gibt, und intermediary.bytes beschwert, so dass die Umwandlung ist nicht eindeutig:

InterpretError: Cannot interpret as bytes unambiguously - not multiple of 8 bits. 

Ich bin nicht zu irgendetwas in dem obigen Code gebunden - jeder Methode, eine Folge von ganzen Zahlen zu nehmen und es in ein Bytearray (mit korrekter Größe in Bytes) zu konvertieren, würde sehr geschätzt werden.

+0

Wozu braucht es das Tag [tag: can]? – usr2564301

+0

@RadLexus ist Teil einer Can-Nachricht. für das vorliegende Problem nicht besonders relevant, nehme ich an. – oirectine

+0

Warum verwenden Sie nicht die Nachrichtenstruktur der Register Ihres CAN-Controllers? Kennung und Länge sind dedizierte Felder des CAN-Rahmens, während diese anderen Dinge im Datenfeld gespeichert werden müssen. – Lundin

Antwort

2

Wenn es eine bytearray ist, die Sie möchten, dann wäre die einfache Option, direkt dorthin zu springen und es direkt aufzubauen. Etwas wie folgt aus:

# Define some values: 
from_address = 14 
control_byte = 10 
identifier = 80 
length = 109 

# Create a bytearray with 8 spaces: 
message = bytearray(8) 

# Add from and control: 
message[0] = from_address 
message[1] = control_byte 

# Little endian dropping in of the identifier: 
message[2] = identifier & 255 
message[3] = (identifier >> 8) & 255 
message[4] = (identifier >> 16) & 255 

# Little endian dropping in of the length: 
message[5] = length & 255 
message[6] = (length >> 8) & 255 
message[7] = (length >> 16) & 255 

# Display bytes: 
for value in message: 
    print(value) 

Here's a working example of that.

Gesundheit Warnung

Das geht davon aus, dass die oben Nachricht little endian sein wird erwartet. Es könnte auch in Python so gebaut werden, aber es ist keine Sprache, die ich oft benutze.

Verwandte Themen