来搞清楚CRC校验的原理和实现
在MIPI_CSI-2協議里payload數據的校驗使用了CRC校驗,但是關于CRC校驗只知其一,或者說只知的還不到其一,因此非常有必要搞清楚它,自然的我搜查了一些博主的文章嘗試得到答案,最終在知乎前輩的一篇文章中找到了比較容易理解的內容。
參考:CRC校驗原理及實現 - 知乎 (zhihu.com)
? ? ? ? ? ?CRC校驗(一)——原理 - 菜鳥學院 (noobyard.com)
? ? ? ? ? ??CRC碼計算及校驗原理的最通俗詮釋 - 苦澀的茶 - 博客園 (cnblogs.com)
目錄
- 前言
- CRC算法簡介
- CRC計算
- CRC校驗
- CRC計算的verilog語言實現
- CRC計算工具
- 總結
前言
最近的工作中要實現對通信數據的CRC計算。因此花時間好好研究了一下周末有時間整理筆記。
一個完整的數據幀通常由一下部分構成:
校驗位是為了保證數據在傳輸的過程中的完整性,采用一種指定的算法對原始的數據進行計算,得出的一個校驗值,在接收方接收到數據時,采用同樣的校驗算法對原始的數據進行計算,如果計算結果和接收到的校驗值一致,說明數據校驗正確,這一幀數據可以使用。如果不一致,說明傳輸過程中出現了差錯,這一陣數據丟棄,請求重新發送。
常用的校驗算法有奇偶校驗,校驗和,CRC,還有LRC,BBC等不常用的校驗算法。
以串口通信中的奇校驗為例,如果數據中1的個數位奇數,則奇校驗位為0,否則為1。
例如原始數據為:0001 0011,數據中1的個數(或各位相加)為3,所以奇校驗位為0,這種校驗方法很簡單,但是這種校驗方法有很大的誤碼率,假設由于傳輸過程中的干擾,接受斷接受到的數據是0010 0011,通過奇校驗原酸,得到奇校驗位的值為0,雖然校驗通過,但是數據已經發生了錯誤。
校驗和同理也會有類似的錯誤:
?
一個好的校驗方法,配合數字信號編碼方式,如(差分)曼徹斯特編碼,(不)歸零碼等對數據進行編碼,可大大提高通信的健壯性和穩定性,例如以太網中使用的是CRC-32校驗,本文介紹CRC校驗的原理和實現方法。
CRC算法簡介
循環冗余校驗(Cyclic Redundancy check,CRC)是一種根據網絡數據包或計算機文件等書記產生簡短固定位數校驗碼的一種信道編碼技術,主要用來檢測或校驗數據傳輸或者保存后可能出現的錯誤,它是利用除法以及余數的原理來做錯誤幀檢測的。
CRC校驗計算速度快,檢錯能力強,易于用編碼器等硬件電路實現,從檢錯的正確率與速度成本等方面,都比奇偶校驗方式具有優勢,因而,CRC成為計算機信息通信領域最為普遍的校驗方式,常見應用有以太網/USB通信,壓縮解壓,視頻編碼,圖像存儲,磁盤讀寫等。
CRC參數模型
不知道你是否遇到過這種情況,同樣的CRC多項式,調用不同的CRC計算函數,得到的結果卻不一致,而且和手算的結果也不一樣,這就涉及到CRC的參數模型了,計算一個正確的CRC值,需要知道CRC的參數模型。
一個完整的CRC參數模型應該包含一下信息:WIDTH, POLY, INIT, REFIN, REFOUT, XOROUT
- NAME:參數模型名稱
- WIDTH:?寬度,即生成的CRC數據寬度,如CRC-8,生成CRC為8位
- POLY:十六進行多項式,省略最高位1,如X^8+X^2+X+1,二進制為1 0000 0111,省略最高位1,轉換為16進制為0x07。
- INIT:CRC初始值,和WIDTH位寬一致。
- REFIN:true或者false,在進行計算前,原始數據是否翻轉,eg:原始數據0x34 = 0011 0100
- ? ? ? ? ? ? ? 如果REFIN為ture,進行反轉之后為0010 1100 = 0x2c
- REFOUT:true或者false,運算完成后,得到的CRC值是否進行翻轉,如計算得到的CRC值為:
- ? ? ? ? ? ? ? 0x97 = 1001 0111,如果REFOUT為ture,進行翻轉后為1110 1001 = 0xE9
- XOROUT:計算結果與此參數進行異或運算后得到最終的CRC值,和WIDTH位寬一致。
(PS:首先把生成多項式轉換成二進制數,由G(X)?= X^8?+ X^2?+X+1可以知道(它一共是9位(總位數等于最高位的冪次加1,即8+1=9),然后根據多項式各項的含義(多項式只列出二進制值為1的位,也就是這個二進制的第8位、第3位、第1位、第0位的二進制均為1,其它位均為0)很快就可得到它的二進制比特串為1 0000 0111)
參考了:CRC碼計算及校驗原理的最通俗詮釋 - 苦澀的茶 - 博客園 (cnblogs.com)
通常如果只給了一個多項式,其他的沒有說明,則默認:INIT:0x00,REFIN=false,REFOUT=false,XOROUT=0x00
常用的21個標準CRC參數模型:
| CRC-4/ITU | x4?+ x + 1 | 4 | 03 | 00 | 00 | true | true |
| CRC-5/EPC | x5?+ x3?+ 1 | 5 | 09 | 09 | 00 | false | false |
| CRC-5/ITU | x5?+ x4?+ x2?+ 1 | 5 | 15 | 00 | 00 | true | true |
| CRC-5/USB | x5?+ x2?+ 1 | 5 | 05 | 1F | 1F | true | true |
| CRC-6/ITU | x6?+ x + 1 | 6 | 03 | 00 | 00 | true | true |
| CRC-7/MMC | x7?+ x3?+ 1 | 7 | 09 | 00 | 00 | false | false |
| CRC-8 | x8?+ x2?+ x + 1 | 8 | 07 | 00 | 00 | false | false |
| CRC-8/ITU | x8?+ x2?+ x + 1 | 8 | 07 | 00 | 55 | false | false |
| CRC-8/ROHC | x8?+ x2?+ x + 1 | 8 | 07 | FF | 00 | true | true |
| CRC-8/MAXIM | x8?+ x5?+ x4?+ 1 | 8 | 31 | 00 | 00 | true | true |
| CRC-16/IBM | x16?+ x15?+ x2?+ 1 | 16 | 8005 | 0000 | 0000 | true | true |
| CRC-16/MAXIM | x16?+ x15?+ x2?+ 1 | 16 | 8005 | 0000 | FFFF | true | true |
| CRC-16/USB | x16?+ x15?+ x2?+ 1 | 16 | 8005 | FFFF | FFFF | true | true |
| CRC-16/MODBUS | x16?+ x15?+ x2?+ 1 | 16 | 8005 | FFFF | 0000 | true | true |
| CRC-16/CCITT | x16?+ x12?+ x5?+ 1 | 16 | 1021 | 0000 | 0000 | true | true |
| CRC-16/CCITT-FALSE | x16?+ x12?+ x5?+ 1 | 16 | 1021 | FFFF | 0000 | false | false |
| CRC-16/X25 | x16?+ x12?+ x5?+ 1 | 16 | 1021 | FFFF | FFFF | true | true |
| CRC-16/XMODEM | x16?+ x12?+ x5?+ 1 | 16 | 1021 | 0000 | 0000 | false | false |
| CRC-16/DNP | x16?+ x13?+ x12?+ x11?+ x10?+ x8?+ x6?+ x5?+ x2?+ 1 | 16 | 3D65 | 0000 | FFFF | true | true |
| CRC-32 | x32?+ x26?+ x23?+ x22?+ x16?+ x12?+ x11?+ x10?+ x8?+ x7?+ x5?+ x4?+ x2?+ x + 1 | 32 | 04C11DB7 | FFFFFFFF | FFFFFFFF | true | true |
| CRC-32/MPEG-2 | x32?+ x26?+ x23?+ x22?+ x16?+ x12?+ x11?+ x10?+ x8?+ x7?+ x5?+ x4?+ x2?+ x + 1 | 32 | 04C11DB7 | FFFFFFFF | 00000000 | false | false |
CRC校驗在電子通信領域非常常用,可以說有數據處理的地方就有CRC校驗:
舉幾個例子:
- 美信(MAXIM)的芯片DS2401/DS18B20,都是使用的CRC-8/MAXIM模型
- SD卡或MMC使用的是CRC-7/MMC模型
- Modbus通信協議使用的是CRC-16/MODBUS參數模型
- USB協議中使用的是CRC-5/USB和CRC-16/USB模型
- STM32自帶的硬件CRC計算模塊使用的是CRC-32模型
至于多項式的選擇,初始值和異或值得選擇,輸入輸出是否翻轉,這就這幾到一定得編碼和數學知識了,感興趣得朋友可以了解一下每個CRC模型個個參數得來源,至于每種參數模型得檢錯能力,重復率,需要專業的數學計算了,不在本文討論的范圍內。
CRC計算
好了,了解了CRC參數模型知識,下面手算一個CRC值,來了解CRC計算的原理。
問:原始數據0x34,使用CRC-8/MAXIN參數模型,求CRC值?
?答:根據CRC參數模型表,得到CRC-8/MAXIN的參數如下:
POLY = 0x31 = 0011 0001(最高位1已經省略) INIT = 0x00 XOROUT = 0x00 REFIN = TRUE REFOUT = TRUE?注意:原始數據和參數中的INIT值不是一個東西!!!
有了上面的參數,這樣計算條件才算完整,下面來實際計算:
- 0:原始數據= 0x34 = 0011 0100 , POLY=0x31 = 1 0011 0001
- 1:INIT = 0x00,原始數據和初始值進行異或運算保持不變?
- 2:REFIN為true,需要先對原始數據進行翻轉:0011 0100 ——> 00101100
- 3:原始數據左移8位,即后面補8個0:0010 1100 0000 0000
- 4:把處理后的數據和多項式進行模2除法,求得余數
? ? ? ? ? ? ?原始數據:0010 1100 0000 0000 = 10 1100 0000 0000
? ? ? ? ? ? ? 多項式:1 0011 0001
? ? ? ? ? ? ? 模2除法取余數低8位:1111 1011
- ?5:與XOROUT進行異或,1111 1011 xor 0000 0000 = 1111 1011
- ?6:因為REFOUT為TRUE,對結果進行翻轉得到最終的CRC-8值:1101 1111 = 0xDF
- ?7:數據+CRC :0011 0100 1101 1111 = 0x34DF,相當于原始數據左移8位+余數
看到這里細心的同學肯定會有疑問:
1:為什么step1,原始數據和初始值異或運算保持不變 ?
? ? ? ?答:算法規定在進行上述模2運算之前,需要先將要計算的數據與初始值進行異或,然后再與多項式進行計算。
2:為什么要將原始數據左移8位 ?
? ? ?答:暫時不清楚,這里有提到左移的規則,但是有待商榷
不要跑,CRC沒這么難!(簡單易懂的CRC原理闡述) - SegmentFault 思否
實驗1:
如上所述,對原始數據0x34的模2除法過程如圖中所示:
?
實驗二:
對原始數據0xc,使用CRC-4/ITU參數模型,求CRC值?
?
?與手算結果一致。
?CRC校驗
上面通過筆算的方式,講解了CRC計算的原理,下面來介紹一下如何進行校驗。
按照上面CRC計算的結果,最終的數據幀:0011 0100 1101 1111 = 34DF,前8位0011 0100是原始數據,后8位1101 1111 是 CRC結果。
接收端的校驗有兩種方式,一種是和CRC計算一樣,在本地把接收到的數據和CRC分離,然后在本地對數據進行CRC運算,得到的CRC值和接收到的CRC進行比較,如果一致,說明數據接收正確,如果不一致,說明數據有錯誤。
另一種方法是把整個數據幀進行CRC運算,因為是數據幀相當于把原始數據左移8位,然后加上余數,如果直接對整個數據幀進行CRC運算(除以多項式),那么余數應該為0,如果不為0說明數據出錯
?附上在線CRC校驗計算器:
CRC(循環冗余校驗)在線計算_ip33.com
總結
以上是生活随笔為你收集整理的来搞清楚CRC校验的原理和实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python将两个文件合并_python
- 下一篇: TQ2440中断系统