CRC 計算工具
計算用來確認通訊、檔案與記憶體的資料是否損壞的 CRC(循環冗餘檢查)值。常用的種類可從預設選擇,也能指定寬度、生成多項式、初始值、位元反轉與最後的 XOR,確認是否符合規格書的 CRC。資料較短時,會逐步顯示 CRC 本質上的多項式除法。
結果
- CRC(十六進位)
- –
- CRC(二進位)
- –
- CRC(十進位)
- –
- 資料長度
- –
- 確認值("123456789" 的 CRC)
- –
- 生成多項式(式)
- –
本工具以逐位元的直接方法計算,結果與使用查表的高速實作相同。確認值可用來與規格書或函式庫的值比對,確認參數是否正確。
以圖表檢視
其他輸入維持目前的值,只讓選擇的輸入在目前值的 1/4 到 4 倍之間變化時的結果。紅點是目前的值。
什麼是 CRC:多項式除法的餘數
CRC(循環冗餘檢查)把資料的位元列視為模 2 多項式的係數,用生成多項式去除,並把餘數當作檢查用的值附加上去。在模 2 運算中,加法與減法都是 XOR,因此除法就是重複「開頭為 1 時 XOR 生成多項式,再移一位」。寬度 w 位元的 CRC,會在資料後面補 w 個 0 再除,然後把 w 位元的餘數附在資料後面送出。接收端做同樣的計算,若餘數一致,就判斷資料在傳輸中沒有損壞。將種類設為 CRC-8、資料輸入「A」,即可確認 0100 0001 後面補 8 個 0,再以 x⁸ + x² + x + 1(0x07)相除的過程。
初始值、位元反轉與最後的 XOR
實際標準中的 CRC 並非單純的除法餘數,而是加上幾項約定來定義。初始值讓暫存器從 0 以外的值(多為全 1)開始,使得開頭連續為 0 的資料也會改變結果。輸入的位元反轉是為了配合 UART 與乙太網路等從最低位元開始傳送每個位元組的序列通訊,通常與輸出的位元反轉成對使用。最後的 XOR 則是將結果全部以 1 反轉等操作。例如 CRC-32 定義為多項式 0x04C11DB7、初始值 0xFFFFFFFF、輸入與輸出皆反轉、最後 XOR 0xFFFFFFFF,"123456789" 的 CRC 為 0xCBF43926。即使多項式同為 0x1021,CRC-16/CCITT-FALSE(0x29B1)、XMODEM(0x31C3)與 KERMIT(0x2189)因約定不同,結果也不同。
CRC 能發現的錯誤
只要選對生成多項式,CRC 就能確實發現許多種類的錯誤。寬度 w 位元的 CRC 可檢測所有長度在 w 以下的連續錯誤(叢發錯誤)。若生成多項式含有 x + 1 這個因式,就能檢測所有奇數個位元的錯誤;適當的多項式在一定資料長度內也能檢測所有 2 位元錯誤。其他隨機錯誤被漏掉的機率約為 2⁻ʷ,CRC-32 約為 43 億分之 1。不過 CRC 只能發現錯誤,無法得知是哪個位元出錯,因此需要更正的記憶體等會使用漢明碼等 ECC。
CRC 的使用場合
CRC 用途廣泛,例如乙太網路訊框結尾的 FCS(CRC-32)、PCI Express 的封包、USB、CAN、SD 卡與儲存裝置的命令、ZIP 與 PNG 等檔案格式,以及 Modbus 等工業通訊(CRC-16/MODBUS)。在硬體中,可用只由正反器與 XOR 閘構成的線性回授移位暫存器(LFSR)逐位元計算;在軟體中,則用 256 個值的查表以位元組為單位高速計算。用於 iSCSI 與儲存裝置的 CRC-32C(Castagnoli),在部分 x86 與 Arm 處理器上可用專用指令計算。
確認 CRC 是否符合規格
CRC 值對不上時,幾乎都是某個參數與規格不同。首先比較規格書或函式庫中 "123456789" 的確認值與本工具的確認值是否一致。若不一致,依序檢查初始值、位元反轉、最後的 XOR,以及生成多項式的寫法(是否省略最高位 x^w,或是位元反轉後的形式)。接著確認計算 CRC 的範圍(是否包含標頭),以及傳送時的位元組順序(CRC-16 先送高位位元組還是低位位元組)。在本工具輸入實際通訊中擷取到的十六進位位元組來比對,會更容易找出問題。
練習介面題目
- A即使有錯誤也不處理,直接使用直到軟體發現為止
- B發現錯誤就關閉該裝置的電源
- C在封包附加CRC以偵測錯誤,若有錯誤則通知未能收到並要求重送
查看答案與解析
正確答案:C. 在封包附加CRC以偵測錯誤,若有錯誤則通知未能收到並要求重送
資料連結層會在每個封包附加序號與CRC(循環冗餘檢查)碼後傳送。接收方確認CRC,正確則回傳ACK,有錯誤則回傳NAK;傳送方在取得確認之前會將封包保留在手邊,收到NAK就重新傳送。有了這個機制,即使實體層偶爾發生位元錯誤,上層與軟體也能收到正確的資料。
- A產生偽隨機圖樣,以及測試中的圖樣產生、CRC計算
- B精確計時
- C放大類比訊號
查看答案與解析
正確答案:A. 產生偽隨機圖樣,以及測試中的圖樣產生、CRC計算
只要選擇適當的分接點,LFSR以n位元會循環經過除全0以外的 2ⁿ − 1 種狀態,產生看似隨機的序列(M序列)。由於只需XOR與正反器即可製作,用於內建自我測試(BIST)的圖樣產生與結果壓縮、乙太網路等的CRC計算,以及將訊號平均化以減少電磁雜訊的拌碼器。由於序列可預測,不能用作加密用的亂數。
常見問題
為什麼 CRC-16 有那麼多種?
CRC-16 這個名稱只表示寬度為 16 位元,生成多項式、初始值、位元反轉與最後 XOR 的組合因標準而異。例如 Modbus 使用 CRC-16/MODBUS(0x8005、初始值 0xFFFF、有反轉),XMODEM 則是 0x1021、初始值 0、無反轉。請確認所用標準的參數,再以預設或自訂設定對應。
"123456789" 的確認值是什麼?
這是 ASCII 字串 "123456789"(9 個位元組)的 CRC,每種 CRC 都有固定的值。CRC 目錄與函式庫說明常列出這個值,作為確認參數組合是否正確的依據。CRC-32 為 0xCBF43926,CRC-16/MODBUS 為 0x4B37。
CRC 和檢查和(checksum)有什麼不同?
檢查和是把位元組相加等簡單的計算,容易漏掉資料順序對調或互相抵消的錯誤。CRC 以多項式除法為基礎,能區分位元的位置,確實發現叢發錯誤等。因此通訊與記錄的錯誤檢測主要使用 CRC。
CRC 能更正錯誤嗎?
一般不能。CRC 用來發現是否有錯誤,但無法得知是哪個位元出錯,發現後通常以重送等方式恢復。像記憶體這類無法重送的場合,會使用漢明碼、BCH 碼、LDPC 碼等可更正錯誤的編碼(ECC)。
十六進位位元組要怎麼輸入?
以每個位元組 2 位數的方式輸入,例如「31 32 33」「313233」或「0x31,0x32,0x33」。空白、逗號、冒號、連字號與「0x」都會被忽略。選擇字串時,會先將輸入的字元轉成 UTF-8 位元組再計算。