import can import time from intelhex import IntelHex from crc import Calculator, Crc16 # Конфигурация CAN CAN_CHANNEL = 'socketcan' CAN_INTERFACE = 'can0' CAN_BITRATE = 1000000 # Параметры из заголовочного файла BOOT_CAN_ID = 0x721 DATA_CAN_ID = 0x730 BOOT_CAN_END = 0x722 ACK_CAN_ID = 0x723 # Конфигурация CRC16 CRC16_POLYNOMIAL = 0x8005 # Стандартный полином CRC-16-IBM CRC16_INIT = 0xFFFF def send_firmware(hex_file): bus = can.interface.Bus(channel='can0', bustype='socketcan') # Чтение и преобразование HEX-файла ih = IntelHex(hex_file) binary_data = ih.tobinarray() fw_size = len(binary_data) # Расчет CRC16 # calculator = Calculator(Crc16.CCITT, optimize=True) fw_crc = 0x6933 # Отправка команды START start_data = bytearray([0x01]) start_data += fw_size.to_bytes(4, 'little') start_data += fw_crc.to_bytes(2, 'little') # 2 байта для CRC16 start_msg = can.Message( arbitration_id=BOOT_CAN_ID, data=start_data, is_extended_id=False ) bus.send(start_msg) # Ожидание подтверждения ack = wait_for_ack(bus) if not ack or ack.data[0] != 0x01: print("Ошибка инициализации!") bus.shutdown() return # Отправка данных packet_size = 8 for i in range(0, len(binary_data), packet_size): chunk = binary_data[i:i+packet_size] chunk += b'\x00' * (8 - len(chunk)) data_msg = can.Message( arbitration_id=DATA_CAN_ID, data=chunk, is_extended_id=False ) bus.send(data_msg) ack = wait_for_ack(bus) if not ack or ack.data[0] != 0x02: print("Ошибка передачи данных!") break progress = (i + len(chunk)) / fw_size * 100 print(f"\rПрогресс: {progress:.1f}%", end='') # Завершение передачи finish_msg = can.Message( arbitration_id=BOOT_CAN_END, data=[0xAA], is_extended_id=False ) bus.send(finish_msg) ack = wait_for_ack(bus, timeout=5) if ack and ack.data[0] == 0xAA: print("\nПрошивка успешно загружена!") else: print("\nОшибка верификации!") bus.shutdown() def wait_for_ack(bus, timeout=1.0): start_time = time.time() while time.time() - start_time < timeout: msg = bus.recv(timeout=0.1) if msg and msg.arbitration_id == ACK_CAN_ID: return msg return None if __name__ == "__main__": import sys if len(sys.argv) != 2: print("Использование: python can_flasher.py firmware.hex") sys.exit(1)