2017-01-30 13 views
0

Я пишу код, который создает сообщения, отправляемые через CANBUS с использованием определенного протокола. Пример формата для поля данных такого сообщения является:Преобразование двоичных данных в bytearray с 8-битным кодированием

[FROM_ADDRESS (1 байт)] [control_byte (1 байт)] [идентификатор (3 байта)] [длина (3 байта)]

поле данных должно быть отформатировано как список или bytearray. Мой код в настоящее время выполняет следующие действия:

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

где DataFormat определяются следующим образом:

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

Это именно то, что я хочу его, за исключением случаев, когда FROM_ADDRESS этого числа, которое может быть описано в менее чем 8 бит. В этих случаях bin() возвращает двоичную длину символа не делится на 8 (посторонние нули отбрасываются), и поэтому intermediary.bytes жалуется, что преобразование неоднозначно:

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

Я не привязан ни к чему в коде выше - любой был бы очень полезен метод для принятия последовательности целых чисел и преобразования его в bytearray (с правильной оценкой в ​​байтах).

+0

Для чего нужен тег [tag: can] для? – usr2564301

+0

@RadLexus это часть сообщения can. я не думаю, что это не имеет особого отношения к проблеме. – oirectine

+0

Почему бы не использовать структуру сообщений ваших регистров контроллера CAN? Идентификатор и длина являются выделенными полями кадра CAN, тогда как другие данные должны храниться в поле данных. – Lundin

ответ

2

Если это bytearray, что бы вы хотели, то простым вариантом было бы прыгнуть прямо туда и создать его прямо. Что-то вроде этого:

# 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.

предупреждение здоровья

выше предполагает, что сообщение, как ожидается, будет little endian. Там также могут быть созданы способы сделать это на Python, но это не язык, который я часто использую.