from pathlib import Path def calculate_checksum(data): """ 计算校验域 """ checksum = 0 for i in range(0, len(data), 2): checksum += int(data[i: i+2], 16) return (0x100 - checksum) & 0xFF def file_IntelHex_to_Bin(file_data, base_address=0, len_max=1, **kwargs): """ 将Intel Hex格式文件转换为Bin格式; """ if base_address == 0: if file_data[8] == '2': base_address = int(file_data[9: 13], 16) * 0x10 offset_begin = 16 elif file_data[8] == '4': base_address = int(file_data[9: 13], 16) * 0x10000 offset_begin = 16 else: base_address = 0 offset_begin = 0 base_address += int(file_data[offset_begin + 3: offset_begin + 7], 16) base_address &= ~0x0FFF len_space = len_max result = bytearray(len_space).replace(b'\x00', b'\xff') lines = file_data.split('\n') offset = 0 max_address = 0 for line in lines: if line[0] == ':': checksum = sum([int(x, 16) * (15 * (~i & 0x01) + 1) for i, x in enumerate(line[1:])]) if (checksum & 0x00FF) != 0: raise Exception('Hex file checksum error!') if line[7:9] == '00': len_line = int(line[1:3], 16) address = offset + int(line[3:7], 16) - base_address data = bytearray.fromhex(line[9:-2]) if 'conv_end' in kwargs.keys(): address *= 2 if kwargs['conv_end']: for i in range(0, len_line, 2): t = data[i] data[i] = data[i+1] data[i+1] = t if (address + len_line) > max_address: max_address = address + len_line if max_address >= len_space: if len_max == 1: result += bytearray(max_address - len_space).replace(b'\x00', b'\xff') len_space += max_address - len_space else: raise Exception("Bin file Oversize.") result[address:address+len_line] = data elif line[7:9] == '01': break elif line[7:9] == '02': offset = int(line[9:-2], 16) * 16 elif line[7:9] == '03': pass elif line[7:9] == '04': # 拓展地址偏移 offset = int(line[9:-2], 16) * 2**16 elif line[7:9] == '05': pass return result[:max_address] def file_Bin_to_IntelHex(file_data: bytearray, base_address=0, **kwargs): """ 将Bin格式文件转换为Intel Hex格式; """ chunk_size = 32 rom_width = 8 memory_width = 8 if 'chunk_size' in kwargs.keys(): """ 数据分块大小 """ chunk_size = kwargs['chunk_size'] if 'memory_width' in kwargs.keys(): """ 地址数据位宽 """ memory_width = kwargs['memory_width'] * 8 if 'rom_width' in kwargs.keys(): """ rom数据位宽 """ rom_width = kwargs['rom_width'] * 8 def record_extern_address(address, record_type): """ 添加地址记录 """ if record_type == 4: record_data = (address & 0xFFFF0000) >> 16 elif record_type == 2: record_data = (address & 0xFFFF0) >> 4 else: raise Exception("Unknow record tye.") hex_record = f':020000{record_type:02X}{record_data:04X}' hex_record += f'{calculate_checksum(hex_record[1:]):02X}\n' return hex_record result = str() # 添加开始记录 extern_address = 0 if base_address >= 2 ** 32: """ 超过最大可表示范围, 抛出异常 """ raise Exception("base_address oversize") elif base_address >= 2 ** 16: result += record_extern_address(base_address, 4) extern_address = base_address & 0xFFFF0000 elif base_address >= 2 ** 4: result += record_extern_address(base_address, 2) extern_address = base_address & 0xFFFF0 record_type = 0 binary_offset = 0 while binary_offset < len(file_data): """ 循环分块处理数据 """ data_chunk = file_data[binary_offset: binary_offset + chunk_size] record_len = len(data_chunk) record_data = data_chunk record_addr = (base_address - extern_address + (binary_offset // (memory_width // 8))) if record_addr >= 0x10000: result += record_extern_address((base_address + (binary_offset // (memory_width // 8))), 4) extern_address = (base_address + (binary_offset // (memory_width // 8))) & 0xFFFF0000 continue # 构造记录 hex_record = f':{record_len:02X}{record_addr:04X}{record_type:02X}' hex_record += ''.join(f'{byte:02X}' for byte in record_data) hex_record += f'{calculate_checksum(hex_record[1:]):02X}\n' result += hex_record binary_offset += chunk_size # 添加结束记录 hex_record = f':00000001FF\n' result += hex_record return result def test1(fp: Path): """ bin文件生成测试 """ file1 = Path(fp) path1 = file1.parent / (file1.stem + ".bin") data1 = file1.read_text() data2 = file_IntelHex_to_Bin(data1, 0x3F0100) path1.write_bytes(data2) # 测试Bin到IntelHex bin = Path(fp).read_bytes() result = file_Bin_to_IntelHex(bin, 0x80000, memory_width=2) (fp.parent / (fp.stem + ".hex")).write_text(result)