import xml.etree.ElementTree as ET def make_qspi_mxfile(): # ========== 基础参数 ========== y_cs_high, y_cs_low = 80, 110 y_sclk_high, y_sclk_low = 180, 210 y_io0_high, y_io0_low = 280, 310 y_io1_high, y_io1_low = 380, 410 # 时序参数:50px/周期,36个周期(8命令+24地址+4数据) cycle_w = 50 start_x = 100 n_cycles = 36 # 8 + 24 + 4 end_x = start_x + n_cycles * cycle_w # 1900 tail_x = end_x + 50 # 1950 rise_edges = [start_x + i*cycle_w + cycle_w//2 for i in range(n_cycles)] # 125,175... fall_edges = [start_x + (i+1)*cycle_w for i in range(n_cycles)] # 150,200...1900 # 数据定义 cmd_bits = [0,0,1,1,1,0,1,1] # 0x3B MSB first addr_bytes = [ [0,0,0,1,0,0,1,0], # 0x12 A23-A16 [0,0,1,1,0,1,0,0], # 0x34 A15-A8 [0,1,0,1,0,1,1,0], # 0x56 A7-A0 ] addr_bits = [b for byte in addr_bytes for b in byte] data_io0 = [0,0,0,0] # D0,D2,D4,D6 (示例 0xAA) data_io1 = [1,1,1,1] # D1,D3,D5,D7 all_io0 = cmd_bits + addr_bits + data_io0 all_io1 = [0]*32 + data_io1 # 命令地址期间 IO1 idle/low lines = [] lines.append('') lines.append('') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') # 背景 lines.append(' ') lines.append(f' ') lines.append(' ') # 标题 lines.append(' ') lines.append(' ') lines.append(' ') # MSB / LSB lines.append(' ') lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(f' ') lines.append(' ') # 信号标签 for label, y, eid in [("CS", 85, "label_cs"), ("SCLK", 185, "label_sclk"), ("IO0", 275, "label_io0"), ("IO1", 375, "label_io1")]: lines.append(f' ') lines.append(f' ') lines.append(' ') # 阶段分界虚线 boundaries = [ (start_x + 8*cycle_w, "cmd_addr"), # 500 (start_x + 16*cycle_w, "addr_mid1"), # 900 (start_x + 24*cycle_w, "addr_mid2"), # 1300 (start_x + 32*cycle_w, "addr_data"), # 1700 ] for x, eid in boundaries: lines.append(f' ') lines.append(' ') lines.append(f' ') lines.append(f' ') lines.append(' ') lines.append(' ') # ========== CS 波形 ========== cs_pts = [(80, y_cs_high), (90, y_cs_high), (90, y_cs_low), (tail_x, y_cs_low), (tail_x, y_cs_high), (tail_x+10, y_cs_high)] lines.append(' ') lines.append(' ') lines.append(f' ') lines.append(f' ') lines.append(' ') for x, y in cs_pts[1:-1]: lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(' ') # ========== SCLK 波形 ========== sclk_pts = [(80, y_sclk_low), (start_x, y_sclk_low)] for i in range(n_cycles): rise = rise_edges[i] fall = fall_edges[i] sclk_pts.extend([ (rise, y_sclk_low), (rise, y_sclk_high), (fall, y_sclk_high), (fall, y_sclk_low), ]) sclk_pts.append((tail_x, y_sclk_low)) lines.append(' ') lines.append(' ') lines.append(f' ') lines.append(f' ') lines.append(' ') for x, y in sclk_pts[1:-1]: lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(' ') # ========== IO0 波形 ========== def build_wave_pts(bits, y_hi, y_lo, idle_y): y0 = y_hi if bits[0] else y_lo pts = [(80, y0), (start_x, y0)] for i in range(len(bits)-1): end_x = fall_edges[i] y_curr = y_hi if bits[i] else y_lo y_next = y_hi if bits[i+1] else y_lo pts.append((end_x, y_curr)) if y_next != y_curr: pts.append((end_x, y_next)) pts.append((end_x := fall_edges[len(bits)-1], y_hi if bits[-1] else y_lo)) pts.append((tail_x, pts[-1][1])) return pts io0_pts = build_wave_pts(all_io0, y_io0_high, y_io0_low, y_io0_low) lines.append(' ') lines.append(' ') lines.append(f' ') lines.append(f' ') lines.append(' ') for x, y in io0_pts[1:-1]: lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(' ') # ========== IO1 波形 ========== io1_pts = build_wave_pts(all_io1, y_io1_high, y_io1_low, y_io1_low) lines.append(' ') lines.append(' ') lines.append(f' ') lines.append(f' ') lines.append(' ') for x, y in io1_pts[1:-1]: lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(' ') # ========== 命令 bit 标签(IO0 上方) ========== cmd_labels = ["0","0","1","1","1","0","1","1"] for i, val in enumerate(cmd_labels): cx = rise_edges[i] lines.append(f' ') lines.append(f' ') lines.append(' ') # ========== 阶段名称标签 ========== stage_labels = [ (start_x + 4*cycle_w, "命令 (0x3B)", "#4CAF50"), (start_x + 12*cycle_w, "地址 [23:16]", "#666666"), (start_x + 20*cycle_w, "地址 [15:8]", "#666666"), (start_x + 28*cycle_w, "地址 [7:0]", "#666666"), (start_x + 34*cycle_w, "数据 (Dual)", "#2196F3"), ] for x, txt, color in stage_labels: lines.append(f' ') lines.append(f' ') lines.append(' ') # ========== 数据阶段 bit 标签 ========== data_labels_io0 = ["D0","D2","D4","D6"] data_labels_io1 = ["D1","D3","D5","D7"] for i in range(4): cx = rise_edges[32 + i] # IO0 lines.append(f' ') lines.append(f' ') lines.append(' ') # IO1 lines.append(f' ') lines.append(f' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append('') return "\n".join(lines) xml_content = make_qspi_mxfile() output_path = "SPI_Waveform_QSPI.drawio" with open(output_path, "w", encoding="utf-8") as f: f.write(xml_content) print("文件已生成:", output_path)