2026年1月15日 星期四

CRC(循環冗餘檢查)

 CRC(循環冗餘檢查)

完整的 CRC(循環冗餘檢查)逐步演示器。它支援自定義生成多項式資料位元流,並透過「下一步」按鈕展示二進制長除法(XOR 運算)的過程。

  • 二進制長除法模擬

    • CRC 的核心是模二除法(Modulo-2 Division),實務上就是不斷進行 XOR(互斥或)

    • 程式會自動在資料後方補零(數量等於多項式長度減一)。

  • 產生器 vs 檢查器

    • 產生器 (Generator):輸入原始資料(如 1101),得到的餘數就是 CRC 碼。發送時,會將此 CRC 碼附加在原始資料後方。

    • 檢查器 (Checker):輸入「原始資料 + CRC 碼」。如果最後算出的餘數為 全 0,則代表傳輸無誤。


    import tkinter as tk

    from tkinter import messagebox


    class CRCApp:

        def __init__(self, root):

            self.root = root

            self.root.title("CRC 循環冗餘檢查逐步演示器")

            self.root.geometry("800x800")


            # 運算狀態變數

            self.data_bits = []      # 原始資料 + 補零

            self.poly_bits = []      # 生成多項式

            self.current_divisor_pos = 0

            self.temp_remainder = []

            self.steps_log = []


            self.create_widgets()


        def create_widgets(self):

            # 輸入區

            input_frame = tk.LabelFrame(self.root, text=" 參數設定 ", padx=10, pady=10)

            input_frame.pack(fill=tk.X, padx=20, pady=10)


            # 1. 生成多項式

            tk.Label(input_frame, text="1) 生成多項式 (例如 CRC-4: 10011):").grid(row=0, column=0, sticky=tk.W)

            self.ent_poly = tk.Entry(input_frame, font=("Courier New", 12), width=30)

            self.ent_poly.insert(0, "10011")

            self.ent_poly.grid(row=0, column=1, padx=10, pady=5)


            # 2. 資料位元流

            tk.Label(input_frame, text="2) 資料位元流 (Binary Bit Stream):").grid(row=1, column=0, sticky=tk.W)

            self.ent_data = tk.Entry(input_frame, font=("Courier New", 12), width=30)

            self.ent_data.insert(0, "1101011011")

            self.ent_data.grid(row=1, column=1, padx=10, pady=5)


            # 按鈕區

            btn_frame = tk.Frame(self.root)

            btn_frame.pack(pady=10)

            

            tk.Button(btn_frame, text="初始化運算", command=self.init_crc, bg="#eee", width=15).pack(side=tk.LEFT, padx=5)

            self.btn_next = tk.Button(btn_frame, text="下一步 >>", command=self.next_step, 

                                      state=tk.DISABLED, bg="#4CAF50", fg="white", font=("Arial", 10, "bold"), width=15)

            self.btn_next.pack(side=tk.LEFT, padx=5)


            # 3. 畫面顯示區 (文字區域)

            tk.Label(self.root, text="演示畫面 (二進制長除法過程):", font=("Arial", 10, "bold")).pack(anchor=tk.W, padx=20)

            self.txt_display = tk.Text(self.root, font=("Courier New", 12), height=25, bg="#000", fg="#0F0", padx=15, pady=15)

            self.txt_display.pack(padx=20, pady=10, fill=tk.BOTH, expand=True)


            # 底部狀態

            self.lbl_status = tk.Label(self.root, text="請輸入參數並點擊初始化", font=("Arial", 12, "bold"), fg="blue")

            self.lbl_status.pack(pady=10)


        def init_crc(self):

            # 讀取並驗證輸入

            d_str = self.ent_data.get().strip()

            p_str = self.ent_poly.get().strip()


            if not all(b in '01' for b in d_str + p_str) or not d_str or not p_str:

                messagebox.showerror("錯誤", "請輸入有效的二進制位元流 (僅限 0 與 1)")

                return


            # CRC 邏輯:在資料後方補上 (多項式長度 - 1) 個零

            n_zeros = len(p_str) - 1

            self.data_bits = [int(b) for b in d_str] + [0] * n_zeros

            self.poly_bits = [int(b) for b in p_str]

            

            self.current_divisor_pos = 0

            self.temp_remainder = self.data_bits[0:len(p_str)]

            

            self.btn_next.config(state=tk.NORMAL)

            self.txt_display.delete(1.0, tk.END)

            self.lbl_status.config(text="計算中...", fg="orange")


            # 初始畫面繪製

            init_info = f"多項式: {p_str} (長度 {len(p_str)})\n"

            init_info += f"待處理資料: {d_str} (補 {n_zeros} 個零)\n"

            init_info += "="*40 + "\n"

            init_info += "".join(map(str, self.data_bits)) + " (被除數)\n"

            self.txt_display.insert(tk.END, init_info)


        def next_step(self):

            p_len = len(self.poly_bits)

            

            # 執行一次 XOR 運算

            divisor = self.poly_bits if self.temp_remainder[0] == 1 else [0] * p_len

            

            # 記錄目前步驟到 Text

            prefix_space = " " * self.current_divisor_pos

            self.txt_display.insert(tk.END, f"{prefix_space}{''.join(map(str, divisor))} (XOR)\n")

            self.txt_display.insert(tk.END, f"{prefix_space}{'-' * p_len}\n")


            # 計算 XOR 結果

            xor_res = []

            for i in range(p_len):

                xor_res.append(self.temp_remainder[i] ^ divisor[i])

            

            # 移除最高位,並從後方拉下一個位元

            next_pos = self.current_divisor_pos + p_len

            if next_pos < len(self.data_bits):

                new_remainder = xor_res[1:] + [self.data_bits[next_pos]]

                self.temp_remainder = new_remainder

                self.current_divisor_pos += 1

                self.txt_display.insert(tk.END, f"{' ' * self.current_divisor_pos}{''.join(map(str, self.temp_remainder))}\n")

                self.txt_display.see(tk.END)

            else:

                # 結束,最後的結果即為餘數 (Check value)

                remainder = "".join(map(str, xor_res[1:]))

                self.txt_display.insert(tk.END, f"\n最終餘數 (CRC Check Value): {remainder}\n")

                self.lbl_status.config(text=f"完成!CRC 碼: {remainder}", fg="blue")

                self.btn_next.config(state=tk.DISABLED)


    if __name__ == "__main__":

        root = tk.Tk()

        app = CRCApp(root)

        root.mainloop()


    沒有留言:

    張貼留言

    CRC(循環冗餘檢查)

      CRC(循環冗餘檢查) 完整的 CRC(循環冗餘檢查)逐步演示器 。它支援自定義 生成多項式 與 資料位元流 ,並透過「下一步」按鈕展示二進制長除法(XOR 運算)的過程。 二進制長除法模擬 : CRC 的核心是模二除法(Modulo-2 Division),實務上就是不斷進...