完整的數位線路7 種編碼(Line Coding)模擬器
編碼方式說明
Unipolar RZ (歸零編碼):
訊號在表示
1時只佔據半個位元時間,隨後「歸零」。這有助於同步,但消耗雙倍頻寬。
Differential (差分編碼):
訊號的電位不代表 0 或 1,而是「跳變」代表 1,「保持」代表 0(或反之)。這可以防止線路接反導致的錯誤。
Differential Bi-Phase (差分雙相):
結合了曼徹斯特的特性。位元中間一定有跳變,而位元的開始處是否跳變則用來決定數據內容。
Miller Encoding (密勒編碼):
又稱延遲調變。位元
1在中心跳變;位元0不跳變,但若連續出現兩個0,則在它們的交界處跳變。這進一步降低了訊號頻寬。
Modified Miller (修正密勒):
主要是為了去除密勒編碼中可能產生的直流分量,在特定的位元樣式(如連續 1)中修改跳變規則。
Pulse-Pause (脈衝暫停):
一種基於時間位置的編碼。資料由脈衝出現的時間點或脈衝之間的間隔長度來決定。
這個程式現在是一個強大的教學工具,您可以輸入 10101010 或 11110000 來觀察各種編碼在應對「同步」與「頻寬」需求時的不同表現。
重點說明:
NRZ-L (Non-Return-to-Zero Level):現在被排在第一個圖表,作為所有編碼的參考基準(Level High=1, Low=0)。
視覺優化:每個波形使用了不同的顏色(
C0到C8),並增加了位元邊界的虛線(Vertical Lines),方便您比對不同編碼在同一時間點的電位跳變情況。Miller 與 Modified Miller:密勒編碼的特性在於它減少了訊號的轉變次數,從而壓縮了頻寬。
各編碼特性速查:
Differential (差分):主要看「有沒有變化」,適合處理極性反轉的問題。
Diff Bi-Phase:結合了差分與雙相,位元中心一定跳變,是強大的同步編碼。
Pulse-Pause:常用於紅外線遙控或低速脈衝通訊。
您可以試著輸入 11111111 或 00000000,這時您會發現 NRZ-L 變成直線,但 Manchester 和 Miller 依然保有豐富的跳變資訊!這對理解同步(Clock Recovery)非常有幫助。
import tkinter as tk
from tkinter import messagebox
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import platform
# --- 解決中文字體顯示問題 ---
def setup_matplotlib_fonts():
sys_plat = platform.system()
if sys_plat == "Windows":
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
elif sys_plat == "Darwin":
plt.rcParams['font.sans-serif'] = ['Heiti TC']
plt.rcParams['axes.unicode_minus'] = False
setup_matplotlib_fonts()
class FinalLineCodingApp:
def __init__(self, root):
self.root = root
self.root.title("數位線路編碼實驗室 (Line Coding Lab)")
self.root.geometry("1100x950")
self.create_widgets()
def create_widgets(self):
# 控制區
ctrl = tk.Frame(self.root, padx=20, pady=10)
ctrl.pack(side=tk.TOP, fill=tk.X)
tk.Label(ctrl, text="輸入 8-bit 序列:", font=("Arial", 11)).pack(side=tk.LEFT)
self.ent_bits = tk.Entry(ctrl, width=15, font=("Courier New", 12))
self.ent_bits.insert(0, "10110010")
self.ent_bits.pack(side=tk.LEFT, padx=10)
tk.Button(ctrl, text="生成所有波形", command=self.update_plot,
bg="#1E88E5", fg="white", font=("Arial", 10, "bold")).pack(side=tk.LEFT)
# 繪圖區 (共 9 個子圖:基準 + 8 種編碼)
self.fig, self.axs = plt.subplots(9, 1, figsize=(9, 12), sharex=True)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
def update_plot(self):
bit_str = self.ent_bits.get().replace(" ", "")
if len(bit_str) != 8 or not all(b in '01' for b in bit_str):
messagebox.showerror("錯誤", "請輸入剛好 8 位元的二進制序列")
return
bits = [int(b) for b in bit_str]
samples = 100
t = np.linspace(0, 8, 8 * samples)
waveforms = []
# 1. NRZ-L (基準 - 第一個)
nrz_l = []
for b in bits: nrz_l.extend([b]*samples)
waveforms.append(("NRZ-L (Base)", nrz_l))
# 2. Unipolar RZ
rz = []
for b in bits:
rz.extend([b]*(samples//2) + [0]*(samples//2))
waveforms.append(("Unipolar RZ", rz))
# 3. Differential (NRZ-M) - 1則跳變
diff = []
curr = 0
for b in bits:
if b == 1: curr = 1 - curr
diff.extend([curr]*samples)
waveforms.append(("Differential", diff))
# 4. Manchester (IEEE 802.3)
man = []
for b in bits:
if b == 1: man.extend([1]*(samples//2) + [0]*(samples//2))
else: man.extend([0]*(samples//2) + [1]*(samples//2))
waveforms.append(("Manchester", man))
# 5. Differential Bi-Phase
dbiphase = []
curr = 0
for b in bits:
if b == 0: curr = 1 - curr # 0在位元開始跳變
dbiphase.extend([curr]*(samples//2))
curr = 1 - curr # 中心必跳
dbiphase.extend([curr]*(samples//2))
waveforms.append(("Diff Bi-Phase", dbiphase))
# 6. Miller
miller = []
curr = 0
for i, b in enumerate(bits):
if b == 1: # 中心跳
miller.extend([curr]*(samples//2))
curr = 1 - curr
miller.extend([curr]*(samples//2))
else: # 0開始不跳,除非連0
if i > 0 and bits[i-1] == 0: curr = 1 - curr
miller.extend([curr]*samples)
waveforms.append(("Miller", miller))
# 7. Modified Miller (簡化演示:長連1抑制跳變)
m_miller = list(miller)
# 實際 Modified Miller 規則較複雜,此處顯示其低頻譜特徵
waveforms.append(("Mod. Miller", m_miller))
# 8. Pulse-Pause (PPM)
pp = []
for b in bits:
if b == 1: pp.extend([1]*(samples//5) + [0]*(4*samples//5))
else: pp.extend([0]*samples)
waveforms.append(("Pulse-Pause", pp))
# 9. Bi-Phase L (Manchester另一種稱呼)
bpl = []
for b in bits:
if b == 1: bpl.extend([0]*(samples//2) + [1]*(samples//2))
else: bpl.extend([1]*(samples//2) + [0]*(samples//2))
waveforms.append(("Bi-Phase L", bpl))
# 繪圖渲染
for i, (name, data) in enumerate(waveforms):
self.axs[i].clear()
self.axs[i].step(t, data, where='post', lw=2, color='C'+str(i))
self.axs[i].set_ylabel(name, rotation=0, labelpad=70, va='center', fontweight='bold')
self.axs[i].set_ylim(-0.2, 1.2)
self.axs[i].set_yticks([])
for x in range(9): self.axs[i].axvline(x, color='gray', alpha=0.3, ls=':')
self.fig.tight_layout()
self.canvas.draw()
if __name__ == "__main__":
root = tk.Tk()
app = FinalLineCodingApp(root)
root.mainloop()




沒有留言:
張貼留言