IOS14443B 讀取器至電子標籤 調變及編碼方式
根據 ISO 14443-B 標準,ASK 10% 的調變指數實務上通常落在 8% 到 14% 之間。
核心原理解析
NRZ 編碼 (Non-Return-to-Zero):逻辑 '1' 代表高電位,逻辑 '0' 代表低電位。在位元持續時間內,電平保持不變。
ASK 10% 調變:載波(Carrier)在邏輯低位時不會歸零,而是下降到最大振幅的約 90%。
計算公式:m = {A - B} / {A + B},其中 A 是最大振幅, B 是最小振幅。
若 m = 10%,則 B ≈ 0.818 * A 。
Python 實作程式碼
import tkinter as tk
from tkinter import messagebox
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class ISO14443BSimulator:
def __init__(self, root):
self.root = root
self.root.title("ISO 14443-B ASK 10% 模擬器")
# --- UI 介面佈局 ---
control_frame = tk.Frame(root)
control_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=10)
tk.Label(control_frame, text="二進位位元流 (Bit Stream):").pack(side=tk.LEFT)
self.bit_entry = tk.Entry(control_frame, width=25)
self.bit_entry.insert(0, "101101")
self.bit_entry.pack(side=tk.LEFT, padx=5)
self.btn_plot = tk.Button(control_frame, text="繪製波形", command=self.plot_waveform, bg="#e1e1e1")
self.btn_plot.pack(side=tk.LEFT, padx=5)
# Matplotlib 畫布設定
# tight_layout 確保標籤不會被切到
self.fig, self.ax = plt.subplots(figsize=(8, 4.5), dpi=100)
self.canvas = FigureCanvasTkAgg(self.fig, master=root)
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
def plot_waveform(self):
bits_str = self.bit_entry.get().strip()
# 檢查輸入是否合法
if not bits_str or not all(b in '01' for b in bits_str):
messagebox.showerror("錯誤", "請輸入有效的二進位字串 (僅限 0 與 1)")
return
bits = [int(b) for b in bits_str]
# 模擬參數
fs = 500 # 每個 bit 的取樣點數
carrier_freq = 10 # 載波頻率
total_points = len(bits) * fs
t = np.linspace(0, len(bits), total_points)
# 1. 生成 NRZ 信號 (用於包絡線)
# ISO 14443-B: 1 = 高振幅 (A), 0 = 低振幅 (B)
# 若指數為 10%, 則 B ≈ 0.82 * A
A = 1.0
B = 0.818
envelope = np.repeat([A if b == 1 else B for b in bits], fs)
# 2. 生成載波並進行 ASK 調變
carrier = np.sin(2 * np.pi * carrier_freq * t)
ask_signal = envelope * carrier
# --- 開始繪圖 ---
self.ax.clear()
# 繪製 ASK 調變波形 (藍色實線)
self.ax.plot(t, ask_signal, color='#1f77b4', label='ASK 10% (ISO 14443-B)', linewidth=1)
# 繪製原始 NRZ 數據參考線 (紅色虛線)
# 為了美觀,將 0/1 映射到對應的振幅高度
nrz_display = np.repeat([A if b == 1 else B for b in bits], fs)
self.ax.plot(t, nrz_display, color='red', linestyle='--', alpha=0.7, label='NRZ Data')
# 設定圖表格式
self.ax.set_ylim(-1.3, 1.5)
self.ax.set_title(f"ISO 14443-B Modulation Simulation", fontsize=12)
self.ax.set_xlabel("Bit Period")
self.ax.set_ylabel("Amplitude")
self.ax.grid(True, which='both', linestyle=':', alpha=0.6)
# --- 關鍵修改:將圖例移至右下角 ---
# loc='lower right' 指定位置
# frameon=True 加上外框以利辨識
self.ax.legend(loc='lower right', frameon=True, shadow=True, fontsize='small')
self.fig.tight_layout()
self.canvas.draw()
if __name__ == "__main__":
root = tk.Tk()
# 設定視窗初始大小
root.geometry("850x550")
app = ISO14443BSimulator(root)
# 啟動時先畫一次預設值
app.plot_waveform()
root.mainloop()

沒有留言:
張貼留言