所有1-Wire器件(包括iButton器件)在只讀存儲器(ROM)中包含一個8字節(jié)的唯一注冊號。該注冊號用作1-Wire總線上的唯一網(wǎng)絡(luò)地址。為確保數(shù)據(jù)通信的完整性,每個注冊號的一個字節(jié)為1-Wire CRC字節(jié)。本應(yīng)用筆記解釋了如何計算這種8位1-Wire CRC。它還繼續(xù)解釋用于驗證保存在設(shè)備內(nèi)存中的記錄的 16 位 CRC。1-Wire CRC和CRC-16均在選定的1-Wire器件的硬件中生成,以驗證數(shù)據(jù)。??
介紹
Maxim iButton產(chǎn)品是一系列器件,它們都按照稱為1-Wire協(xié)議的特定命令序列通過單線進行通信。每個器件的一個關(guān)鍵特性是在制造時寫入每個部件的唯一 8 字節(jié) ROM 代碼。此 8 字節(jié)代碼的組件如圖 1 所示。最低有效字節(jié)包含標識 iButton 產(chǎn)品類型的系列代碼。例如,DS1990A的家族代碼為01十六進制,DS1922L的家族代碼為41十六進制。由于相同或不同系列類型的多個器件可以同時駐留在同一條1-Wire總線上,因此主機必須確定如何正確訪問其位于1-Wire總線上的每個器件。家庭代碼提供了此信息。接下來的 6 個字節(jié)包含一個唯一的序列號,允許將同一系列代碼中的多個設(shè)備相互區(qū)分。這個唯一的序列號可以看作是1-Wire總線上每個器件的“地址”。整個設(shè)備集合加上主機,形成了一種微型局域網(wǎng)或MicroLAN;它們都通過單根公共線路進行通信。每個器件的ROM代碼中的最高有效字節(jié)包含一個循環(huán)冗余校驗(CRC)值,該值基于該部分的前7個字節(jié)的數(shù)據(jù)。當主機系統(tǒng)開始與設(shè)備通信時,首先讀取 8 字節(jié) ROM,首先讀取 LSB。如果主機計算的CRC與ROM數(shù)據(jù)第7字節(jié)中包含的CRC一致,則可以認為通信有效。如果不是這種情況,則發(fā)生了錯誤,應(yīng)再次讀取ROM代碼。
圖1.iButton系統(tǒng)配置使用1-Wire CRC。
一些iButton產(chǎn)品除了具有主機系統(tǒng)可以使用適當命令訪問的8字節(jié)ROM之外,還具有高達8kB的隨機存取存儲器(RAM)。即使iButton設(shè)備沒有板載CRC硬件,如果主機能夠計算ROM代碼的CRC值,那么也可以開發(fā)使用CRC在設(shè)備的RAM部分存儲和檢索數(shù)據(jù)的程序。數(shù)據(jù)可以正常方式寫入設(shè)備;然后,主機計算的CRC值將附加并與數(shù)據(jù)一起存儲。當從iButton設(shè)備檢索此數(shù)據(jù)時,該過程將反轉(zhuǎn)。主機將為數(shù)據(jù)字節(jié)計算的 CRC 值與作為該數(shù)據(jù)的 CRC 存儲在內(nèi)存中的值進行比較。如果值相等,則從iButton設(shè)備讀取的數(shù)據(jù)可以被視為有效。為了利用CRC的強大功能來驗證1-Wire總線上的串行通信,必須了解CRC是什么以及它們是如何工作的。此外,硬件或軟件實現(xiàn)都需要一種由主機計算CRC值的實用方法。
背景
可以通過多種方式檢查串行數(shù)據(jù)是否存在錯誤。一種常見的方法是在每個正在檢查的數(shù)據(jù)包中包含額外的位,以指示是否發(fā)生了錯誤。例如,對于 8 位 ASCII 字符的數(shù)據(jù)包,每個 ASCII 字符都會附加一個額外的位,指示該字符是否包含錯誤。假設(shè)數(shù)據(jù)由 11010001 位字符串組成。一 9千位將被附加,因此 1 的總位數(shù)始終是奇數(shù)。因此,將附加一個 1,數(shù)據(jù)包將變?yōu)?11010001。帶下劃線的字符表示使完整的 9 位數(shù)據(jù)包具有奇數(shù)位數(shù)所需的奇偶校驗位值。如果接收到的數(shù)據(jù)是111010001的,則假定該信息是正確的。但是,如果收到的數(shù)據(jù)是111010101,其中 7千左邊的位被錯誤地接收,1 的總數(shù)不再奇數(shù),并且檢測到錯誤條件并采取適當?shù)拇胧_@種類型的方案稱為奇偶校驗。同樣,也可以選擇1的總數(shù)始終等于偶數(shù),因此稱為偶數(shù)奇偶校驗。但是,此方案僅限于檢測奇數(shù)位錯誤。在上面的示例中,如果數(shù)據(jù)損壞并變得111011101,其中 6千和 7千左邊的位是錯誤的,奇偶校驗看起來是正確的;然而,無論使用偶數(shù)奇偶校驗還是奇偶校驗,都不會檢測到錯誤。
描述
馬克西姆1線CRC
在以最少的硬件量定位串行數(shù)據(jù)流中的錯誤時,最有效的錯誤檢測方案是CRC。本文介紹了Maxim產(chǎn)品中使用的CRC函數(shù)的操作和性質(zhì),而不涉及證明語句和描述的數(shù)學細節(jié)。CRC屬性背后的數(shù)學概念在參考文獻中有詳細的描述。CRC最容易理解的是考慮該功能,因為它實際上是內(nèi)置在硬件中的,通常表示為帶有反饋的移位寄存器排列,如圖2所示?;蛘?,CRC 有時被稱為虛擬變量 X 中的多項式表達式,每個項都有二進制系數(shù)。系數(shù)直接對應(yīng)于移位寄存器實現(xiàn)中顯示的反饋路徑。硬件描述的移位寄存器中的級數(shù)或多項式表達式中存在的最高階系數(shù)表示計算的 CRC 值的大小。數(shù)字數(shù)據(jù)通信中常用的CRC代碼包括CRC-16和CRC-CCITT,每個代碼都計算16位CRC值。Maxim 1-Wire CRC幅度為8位,用于檢查寫入每個64-Wire產(chǎn)品的1位ROM代碼。該ROM代碼由寫入最低有效字節(jié)的8位家族代碼,寫入接下來48個字節(jié)的唯一6位序列號以及基于ROM的前56位計算然后寫入最高有效字節(jié)的CRC值組成。圖2中由異或門表示的反饋路徑的位置,或多項式表達式中系數(shù)的存在,決定了CRC的屬性以及算法定位數(shù)據(jù)中某些類型錯誤的能力。對于1-Wire CRC,可檢測的錯誤類型包括:
64 位數(shù)字內(nèi)任意位置的任何奇數(shù)錯誤。
64 位數(shù)字內(nèi)的任何位置的所有雙位錯誤。
可以包含在 8 位“窗口”中的任何錯誤集群(1-8 位不正確)。
大多數(shù)較大的錯誤群集。
輸入數(shù)據(jù)與圖2中移位寄存器第八級的輸出是非或的。移位寄存器在數(shù)學上可以視為分頻電路。輸入數(shù)據(jù)是除數(shù),帶有反饋的移位寄存器充當除數(shù)。結(jié)果商被丟棄,其余部分是該特定輸入數(shù)據(jù)流的CRC值,該值在最后一個數(shù)據(jù)位移入后駐留在移位寄存器中。從移位寄存器實現(xiàn)中可以明顯看出,最終結(jié)果(CRC值)以一種非常復(fù)雜的方式依賴于所呈現(xiàn)位的過去歷史。因此,需要極其罕見的錯誤組合才能逃脫這種方法的檢測。
圖2.馬克西姆 1 線 8 位 CRC。
示例2中的示例在顯示每個數(shù)據(jù)位后計算CRC值。移位寄存器電路在計算開始時始終復(fù)位為0。計算從 64 位 ROM 的 LSB 開始,這是本例中的 02 十六進制系列代碼。輸入所有56個數(shù)據(jù)位(序列號+族碼)后,移位寄存器中包含的值為A2十六進制,即該輸入流的1-Wire CRC值。如果已經(jīng)計算出的CRC值(在本例中為A2十六進制)現(xiàn)在用作接下來8位數(shù)據(jù)的移位寄存器的輸入,則輸入整個64位數(shù)據(jù)后移位寄存器中的最終結(jié)果應(yīng)全部為0。對于1-Wire CRC算法,此屬性始終成立。如果移位寄存器中出現(xiàn)的任何 8 位值也用作輸入流中的下一個 8 位,則移位寄存器中出現(xiàn)的結(jié)果在 8千數(shù)據(jù)位已移入始終為 00 十六進制。這可以通過觀察8千移位寄存器的級始終等于輸入數(shù)據(jù)位,使得控制反饋的EXOR門的輸出和移位寄存器第一級的下一個狀態(tài)值始終等于邏輯0。這導(dǎo)致移位寄存器在每個數(shù)據(jù)位顯示時簡單地從左向右偏移 0,直到整個寄存器在 0 之后用 8 填充千位。Maxim 1-Wire 64位ROM的結(jié)構(gòu)利用這一特性來簡化用于讀取ROM的器件的硬件設(shè)計。清除主機中的移位寄存器,然后讀取64個ROM位,包括CRC值。如果發(fā)生了正確的讀數(shù),則移位寄存器再次全為0,這是一個容易檢測到的情況。如果移位寄存器中保留非零值,則必須重復(fù)讀取操作。
到目前為止,討論主要圍繞CRC工藝的硬件表示,但顯然,與硬件方法并行的軟件解決方案是計算1-Wire CRC值的另一種方法。示例 1 中給出了如何對過程進行編碼的示例。請注意,具有常數(shù)18十六進制的A寄存器的XRL(異或)是由于在第四級和第五級之后1-Wire CRC中存在EXOR反饋門,如圖2所示。另一種軟件解決方案是簡單地構(gòu)建一個查找表,該查找表可以直接訪問當前存儲在CRC寄存器中的任何8位值和任何8位模式的新數(shù)據(jù)。對于CRC寄存器的當前值為00十六進制的簡單情況,可以計算輸入字節(jié)的256個不同位組合并將其存儲在矩陣中,其中矩陣的索引等于輸入字節(jié)的值(即索引為I = 0到255)??梢宰C明,如果CRC寄存器的當前值不是00十六進制,那么對于任何當前CRC值和任何輸入字節(jié),查找表值與簡化情況相同,但索引到表中的計算采用以下形式:
新CRC = 表 [I] 表示 I = 0 至 255;
其中 I = (當前 CRC) EXOR (輸入字節(jié))
對于當前CRC寄存器值為00十六進制的情況,公式簡化為簡單情況。第二種方法可以減少計算時間,因為操作可以基于字節(jié)完成,而不是前面示例中面向位的命令。但是,存在內(nèi)存容量權(quán)衡,因為查找表必須存儲并消耗 256 字節(jié),而第一個示例除了程序代碼之外幾乎沒有存儲。示例 3 顯示了此類代碼的示例。表 1 顯示了使用查找表方法重復(fù)的前面的示例。1-Wire CRC的兩個特性有助于調(diào)試用于計算CRC值的代碼。對于硬件實現(xiàn),已經(jīng)提到了第一個屬性。如果將CRC寄存器的當前值用作數(shù)據(jù)的下一個字節(jié),則生成的CRC值始終為00十六進制(請參閱上面的解釋)??捎糜诖_認代碼正確操作的第二個屬性是輸入 CRC 寄存器當前值的 1 補碼。對于1-Wire CRC算法,得到的CRC值始終為35十六進制或53十進制。其原因可以通過觀察輸入1的補碼數(shù)據(jù)時CRC寄存器的操作來解釋,如表2所示。
例 1.匯編語言程序
DO_CRC: PUSH ACC ;save accumulator PUSH B ;save the B register PUSH ACC ;save bits to be shifted MOV B,#8 ;set shift = 8 bits ; CRC_LOOP: XRL A,CRC ;calculate CRC RRC A ;move it to the carry MOV A,CRC ;get the last CRC value JNC ZERO ;skip if data = 0 XRL A,#18H ;update the CRC value ; ZERO: RRC A ;position the new CRC MOV CRC,A ;store the new CRC POP ACC ;get the remaining bits RR A ;position the next bit PUSH ACC ;save the remaining bits DJNZ B,CRC_LOOP ;repeat for eight bits POP ACC ;clean up the stack POP B ;restore the B register POP ACC ;restore the accumulator RET
例 2.1-Wire CRC的計算示例
CRC價值 | 輸入值 |
00000000 | 0 |
00000000 | 1 |
10001100 | 0 2 |
01000110 | 0___ |
00100011 | 0 |
10011101 | 0 |
11000010 | 0 0 |
01100001 | 0___ |
10111100 | 0 |
01011110 | 0 |
00101111 | 1 字節(jié) |
00010111 | 1___ |
00001011 | 1 |
00000101 | 0 |
10001110 | 0 1 |
01000111 | 0___ |
10101111 | 0 |
11011011 | 0 |
11100001 | 0 8 |
11111100 | 1___ |
11110010 | 1 |
11110101 | 1 |
01111010 | 0 字節(jié) |
00111101 | 1___ |
00011110 | 1 |
10000011 | 0 |
11001101 | 0 1 |
11101010 | 0___ |
01110101 | 0 |
10110110 | 0 |
01011011 | 0 0 |
10100001 | 0___ |
11011100 | 0 |
01101110 | 0 |
00110111 | 0 0 |
10010111 | 0___ |
11000111 | 0 |
11101111 | 0 |
11111011 | 0 0 |
11110001 | 0___ |
11110100 | 0 |
01111010 | 0 |
00111101 | 0 0 |
10010010 | 0___ |
01001001 | 0 |
10101000 | 0 |
01010100 | 0 0 |
00101010 | 0___ |
00010101 | 0 |
10000110 | 0 |
01000111 | 0 0 |
10101101 | 0___ |
11011010 | 0 |
01101101 | 0 |
10111010 | 0 0 |
01011101 | 0___ |
10100010 = A2 十六進制 = [00000001B81C (序列號) + 02(家庭代碼)] 的 CRC 值] | |
10100010 | 0 |
01010001 | 1 |
00101000 | 0 2 |
00010100 | 0___ |
00001010 | 0 |
00000101 | 1 |
00000010 | 0 ? |
00000001 | 1___ |
00000000 = 00 十六進制 = A2 的 CRC 值 [(CRC) + 00000001B81C(序列號)+ 02(家庭代碼)] |
例 3.1線CRC查找功能
Var CRC : Byte; Procedure Do_CRC(X: Byte); { This procedure calculates the cumulative Maxim 1-Wire CRC of all bytes passed to it. The result accumulates in the global variable CRC. } Const Table : Array[0..255] of Byte = ( 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53); Begin CRC := Table[CRC xor X]; End;
當前 CRC 值 (= 當前表索引) | 輸入數(shù)據(jù) | 新指數(shù)(= 當前 CRC 異或輸入數(shù)據(jù)) | 表 (新索引) (= 新的 CRC 值) |
0000 0000 = 00 十六進制 | 0000 0010 = 02 十六進制 | (00 H xor 02 H) = 02 十六進制 = 2 十進制 | 表[2]= 1011 1100 = BC 十六進制 = 188 dec |
1011 1100 = BC 十六進制 | 0001 1100 = 1C 十六進制 | (BC H xor 1C H) = A0 十六進制 = 160 dec | 表[160]= 1010 1111 = AF 十六進制 = 175 dec |
1010 1111 = 自動對焦六角 | 1011 1000 = B8 十六進制 | (自動對焦 H xor B8 H) = 17 十六進制 = 23 十進制 | 表[23]= 0001 1110 = 1E 十六進制 = 30 dec |
0001 1110 = 1E 十六進制 | 0000 0001 = 01 十六進制 | (1E H xor 01 H) = 1 F 十六進制 = 31 dec | 表[31]= 1101 110 = 直流十六進制 = 220 dec |
1101 1100 = 直流十六進制 | 0000 0000 = 00 十六進制 | (直流高或 00 小時)= 直流十六進制 = 220 十進制 | 表[220]= 1111 0100 = F4 十六進制 = 244 dec |
11110100 = F4 十六進制 | 0000 0000 = 00 十六進制 | (F4 H xor 00 H) = F4 十六進制 = 244 dec | 表 [244]= 0001 0101 = 15 十六進制 = 21 十進制 |
0001 0101 = 15 十六進制 | 0000 0000 = 00 十六進制 | (15 H xor 00 H) = 15 十六進制 = 21 十進制 | 表[21]= 1010 0010 = A2 十六進制 = 162 dec |
1010 0010 = A2 十六進制 | 10100010 = A2 十六進制 | (A2 H xor A2 H) = 十六進制 = 0 十進制 | 表[0]=0000 0000 = 00 十六進制 = 0 十進制 |
CRC寄存器與1的CRC寄存器補充相結(jié)合
X0 | X1 | X2 | X3 | X4 | X5 | X6 | X7 | X7* |
1 | X0 | X1 | X2 | X3* | X4* | X5 | X6 | X6* |
1 | 1 | X0 | X1 | X2* | X3 | X4* | X5 | X5* |
1 | 1 | 1 | X0 | X1* | X2* | X3 | X4* | X4* |
0 | 1 | 1 | 1 | X0* | X1* | X2 | X3 | X3* |
1 | 0 | 1 | 1 | 0 | X0* | X1* | X2 | X2* |
1 | 1 | 0 | 1 | 0 | 1 | X0* | X1* | X1* |
0 | 1 | 1 | 0 | 1 | 0 | 1 | X0* | X0* |
0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 最終 CRC 值 = 35 十六進制,53 十進制 |
注:X我* = X 的補碼我 |
CRC-16 計算 iButton 設(shè)備中的 RAM 記錄
如介紹中所述,除了在所有iButton設(shè)備中找到的唯一8字節(jié)ROM代碼外,某些iButton設(shè)備還具有RAM。由于RAM中存儲的數(shù)據(jù)量可能比8字節(jié)ROM碼大,Maxim建議使用16位CRC值來保證數(shù)據(jù)的完整性,而不是用于ROM的8位1-Wire CRC。建議的特定CRC通常稱為CRC-16。移位寄存器和多項式表示如圖3所示。該圖顯示,對于 16 位 CRC,移位寄存器包含 16 個階段,多項式表達式具有 16 階項。如前所述,iButton設(shè)備不計算CRC值。主機必須生成該值,然后將 16 位 CRC 值追加到實際數(shù)據(jù)的末尾。由于iButton設(shè)備的“通信通道”(即兩個金屬接觸面)的不確定性,數(shù)據(jù)傳輸可能會遇到通常分為三類的錯誤。首先,短暫的間歇性連接會導(dǎo)致數(shù)據(jù)中出現(xiàn)少量位錯誤,正常的CRC-<>函數(shù)旨在檢測這些錯誤。第二種類型的錯誤發(fā)生在完全失去聯(lián)系時,例如當iButton設(shè)備從閱讀器上移開時。
這會導(dǎo)致數(shù)據(jù)的最后一部分被讀取為邏輯 1,因為主機不會將任何與 iButton 設(shè)備的連接解釋為所有 1。在大多數(shù)情況下,正常的CRC-16功能也可以檢測到這種情況。第三種類型的錯誤是由讀卡器短路引起的,這可能是由iButton設(shè)備未正確插入或在讀卡器中明顯傾斜引起的。讀取器短路會導(dǎo)致主機將數(shù)據(jù)讀取為全部 0。使用 CRC 時,這可能會導(dǎo)致問題,因為確定數(shù)據(jù)有效性的方法是讀取數(shù)據(jù)加上存儲的 CRC 值,并查看在主機上計算的結(jié)果 CRC 是否為 0000 十六進制(對于 16 位 CRC)。如果讀取器短路,則數(shù)據(jù)加上與數(shù)據(jù)一起存儲的CRC值將讀取為全為0,并且發(fā)生了錯誤讀取,但主機計算的CRC錯誤地指示了有效的讀取。為避免這種情況,Maxim建議將計算出的CRC-16值(CRC-16*)的補碼與寫入RAM的數(shù)據(jù)一起存儲。使用未互補的CRC-16值,從iButton器件檢索數(shù)據(jù)的過程與1-Wire CRC外殼類似。也就是說,如果主機中的CRC寄存器初始化為0000十六進制,然后從iButton設(shè)備讀取所有數(shù)據(jù)加上與數(shù)據(jù)一起存儲的CRC-16值,則主機的計算結(jié)果應(yīng)具有0000十六進制,作為最終結(jié)果。相反,如果CRC-16值的補碼與iButton中的數(shù)據(jù)一起存儲,則主機上的CRC寄存器初始化為0000十六進制,并讀取實際數(shù)據(jù)加上存儲的CRC-16*值。生成的 CRC 值應(yīng)為 B001 十六進制才能有效讀取。這極大地改善了系統(tǒng)的操作,因為它不能再被閱讀器的短路所愚弄。CRC-16功能具有這些特性的原因可以用類似于1-Wire CRC外殼的方式顯示出來(見圖3和圖5)。16 位 CRC 的操作在理論上與前面描述的 8 位版本相同,但 CRC 的屬性發(fā)生了變化,因為 16 位值現(xiàn)在可用于錯誤檢測。對于CRC-16功能,可檢測的錯誤類型包括:
數(shù)據(jù)記錄中任何位置的任何奇數(shù)錯誤。
數(shù)據(jù)記錄中任意位置的所有雙位錯誤。
可能包含在 16 位“窗口”內(nèi)的任何錯誤簇(1-16 位不正確)。
大多數(shù)較大的錯誤群集。
圖3.CRC-16 硬件描述和多項式。
CRC-16 功能的硬件實現(xiàn)從圖 3 中給出的描述中很簡單。示例 4 顯示了一個軟件解決方案,該解決方案類似于使用單位操作計算 CRC-16 值的硬件操作。和以前一樣,可以通過使用查找表開發(fā)計算量較少的軟件解決方案。8位1-Wire CRC查找表的基本概念也適用于CRC-16外殼。但是,需要對 8 位情況的過程進行輕微修改,因為如果像以前一樣將 CRC-16 函數(shù)的整個 16 位結(jié)果映射到一個表中,則該表將有 2 個16或 65,536 個條目。示例 5 顯示了另一種方法,其中計算 16 位 CRC 值并將其存儲在兩個 256 個條目表中,一個包含高位字節(jié),另一個包含生成的 CRC 的低位字節(jié)。對于任何當前的 16 位 CRC 值(表示為當前高階字節(jié)的Current_CRC16_Hi和當前低階字節(jié)的Current_CRC16_Lo)以及任何新的輸入字節(jié),確定索引到高階字節(jié)表中以定位新的高階字節(jié) CRC 值 (New_CRC16_Hi) 的公式如下:
New_CRC16_Hi = CRC16_Tabhi[I] 表示 I = 0 到 255;其中 I = (Current_CRC16_Lo) EXOR(輸入字節(jié))
確定索引的公式 進入低位字節(jié)表,用于定位新的低位字節(jié) CRC 值 (New_CRC16_Lo) 表示為:
New_CRC16_Lo = (CRC16_Tablo[I]) EXOR (Current_CRC16_Hi) 對于 I = 0 到 255;
其中 I = (Current_CRC16_Lo) EXOR(輸入字節(jié))
圖 4 顯示了此方法工作原理的示例。
例 4.用于CRC-16計算的匯編語言
crc_lo data 20h ; lo byte of crc calculation (bit addressable) crc_hi data 21h ; hi part of crc calculation ;--------------------------------------------------------------------------- ; CRC16 subroutine. ; - accumulator is assumed to have byte to be crc'ed ; - two direct variables are used crc_hi and crc_lo ; - crc_hi and crc_lo contain the CRC16 result ;--------------------------------------------------------------------------- crc16: ; calculate crc with accumulator push b ; save value of b mov b, #08h ; number of bits to crc. crc_get_bit: rrc a ; get low order bit into carry push acc ; save a for later use jc crc_in_1 ;got a 1 input to crc mov c, crc_lo.0 ;xor with a 0 input bit is bit sjmp crc_cont ;continue crc_in_1: mov c, crc_lo.0 ;xor with a 1 input bit cpl c ;is not bit. crc_cont: jnc crc_shift ; if carry set, just shift cpl crc_hi.6 ;complement bit 15 of crc cpl crc_lo.1 ;complement bit 2 of crc crc_shift mov a, crc_hi ; carry is in appropriate setting rrc a ; rotate it mov crc_hi, a ; and save it mov a, crc_lo ; again, carry is okay rrc a ; rotate it mov crc_lo, a ; and save it pop acc ; get acc back djnz b, crc_get_bit ; go get the next bit pop b ; restore b ret end
例 5.使用查找表的CRC-16匯編語言
crc_lo data 40h ; any direct address is okay crc_hi data 41h tmp data 42h ;--------------------------------------------------------------------------- ; CRC16 subroutine. ; - accumulator is assumed to have byte to be crc'ed ; - three direct variables are used, tmp, crc_hi and crc_lo ; - crc_hi and crc_lo contain the CRC16 result ; - this CRC16 algorithm uses a table lookup ;--------------------------------------------------------------------------- crc16: xrl a, crc_lo ; create index into tables mov tmp, a ; save index push dph ; save dptr push dpl ; mov dptr, #crc16_tablo ; low part of table address movc a, @a+dptr ; get low byte xrl a, crc_hi ; mov crc_lo, a ; save of low result mov dptr, #crc16_tabhi ; high part of table address mov a, tmp ; index movc a, @a+dptr ; mov crc_hi, a ; save high result pop dpl ; restore pointer pop dph ; ret ; all done with calculation crc16_tablo: db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 000h, 0c1h, 081h, 040h, 001h, 0c0h, 080h, 041h db 001h, 0c0h, 080h, 041h, 000h, 0c1h, 081h, 040h crc16_tabhi: db 000h, 0c0h, 0c1h, 001h, 0c3h, 003h, 002h, 0c2h db 0c6h, 006h, 007h, 0c7h, 005h, 0c5h, 0c4h, 004h db 0cch, 00ch, 00dh, 0cdh, 00fh, 0cfh, 0ceh, 00eh db 00ah, 0cah, 0cbh, 00bh, 0c9h, 009h, 008h, 0c8h db 0d8h, 018h, 019h, 0d9h, 01bh, 0dbh, 0dah, 01ah db 01eh, 0deh, 0dfh, 01fh, 0ddh, 01dh, 01ch, 0dch db 014h, 0d4h, 0d5h, 015h, 0d7h, 017h, 016h, 0d6h db 0d2h, 012h, 013h, 0d3h, 011h, 0d1h, 0d0h, 010h db 0f0h, 030h, 031h, 0f1h, 033h, 0f3h, 0f2h, 032h db 036h, 0f6h, 0f7h, 037h, 0f5h, 035h, 034h, 0f4h db 03ch, 0fch, 0fdh, 03dh, 0ffh, 03fh, 03eh, 0feh db 0fah, 03ah, 03bh, 0fbh, 039h, 0f9h, 0f8h, 038h db 028h, 0e8h, 0e9h, 029h, 0ebh, 02bh, 02ah, 0eah db 0eeh, 02eh, 02fh, 0efh, 02dh, 0edh, 0ech, 02ch db 0e4h, 024h, 025h, 0e5h, 027h, 0e7h, 0e6h, 026h db 022h, 0e2h, 0e3h, 023h, 0e1h, 021h, 020h, 0e0h db 0a0h, 060h, 061h, 0a1h, 063h, 0a3h, 0a2h, 062h db 066h, 0a6h, 0a7h, 067h, 0a5h, 065h, 064h, 0a4h db 06ch, 0ach, 0adh, 06dh, 0afh, 06fh, 06eh, 0aeh db 0aah, 06ah, 06bh, 0abh, 069h, 0a9h, 0a8h, 068h db 078h, 0b8h, 0b9h, 079h, 0bbh, 07bh, 07ah, 0bah db 0beh, 07eh, 07fh, 0bfh, 07dh, 0bdh, 0bch, 07ch db 0b4h, 074h, 075h, 0b5h, 077h, 0b7h, 0b6h, 076h db 072h, 0b2h, 0b3h, 073h, 0b1h, 071h, 070h, 0b0h db 050h, 090h, 091h, 051h, 093h, 053h, 052h, 092h db 096h, 056h, 057h, 097h, 055h, 095h, 094h, 054h db 09ch, 05ch, 05dh, 09dh, 05fh, 09fh, 09eh, 05eh db 05ah, 09ah, 09bh, 05bh, 099h, 059h, 058h, 098h db 088h, 048h, 049h, 089h, 04bh, 08bh, 08ah, 04ah db 04eh, 08eh, 08fh, 04fh, 08dh, 04dh, 04ch, 08ch db 044h, 084h, 085h, 045h, 087h, 047h, 046h, 086h db 082h, 042h, 043h, 083h, 041h, 081h, 080h, 040h
圖4.CRC-16的計算和表查找方法的比較。
實施例6給出了一種有趣的中間方法。該代碼使用圖 16 所示的公式對整個當前 CRC 值和輸入字節(jié)進行操作,從而為每個輸入的字節(jié)生成一個 CRC-5 值。還顯示了方程的推導(dǎo),使用字母字符表示當前的 16 位 CRC 值,使用數(shù)字字符表示傳入字節(jié)的位。八班后的結(jié)果得出所示方程。然后,這些方程可用于預(yù)先計算新CRC值的大部分。例如,請注意,數(shù)量ABCDEFGH01234567(定義為所有這些位的EXOR)是當前CRC的傳入數(shù)據(jù)字節(jié)和低位字節(jié)的奇偶校驗。與上述逐位方法和查找表方法相比,此方法減少了計算時間和內(nèi)存空間。最后,提到了可用作測試用例的 CRC-16 函數(shù)的兩個屬性,以幫助調(diào)試任何先前方法的代碼。第一個特性與1-Wire CRC外殼相同。如果CRC寄存器的當前16位內(nèi)容也用作接下來的16位輸入,則生成的CRC值始終為0000十六進制。CRC-16函數(shù)的第二個特性也類似于1-Wire CRC情況,如果CRC寄存器當前1位內(nèi)容的16補碼也用作下一個16位輸入,則得到的CRC值始終為B0 01十六進制。這兩個CRC-16特性的證明與1-Wire CRC外殼的證明類似。
例 6.高速CRC-16計算的匯編語言程序
lo equ 40h ; low byte of CRC hi equ 41h ; high byte of CRC crc16: push acc ; save the accumulator. xrl a, lo mov lo, hi ; move the high byte of the CRC. mov hi, a ; save data xor low(crc) for later mov c, p jnc crc0 xrl lo, #01h ; add the parity to CRC bit 0 crc0: rrc a ; get the low bit in c jnc crc1 xrl lo, #40h ; need to fix bit 6 of the result crc1: mov c, acc.7 xrl a, hi ; compute the results for other bits. rrc a ; shift them into place mov hi, a ; and save them jnc crc2 xrl lo, #80h ; now clean up bit 7 crc2: pop acc ; restore everything and return ret
圖5.高速CRC-16計算方法。
審核比較:郭婷
-
寄存器
+關(guān)注
關(guān)注
31文章
5343瀏覽量
120348 -
存儲器
+關(guān)注
關(guān)注
38文章
7492瀏覽量
163828 -
1-Wir
+關(guān)注
關(guān)注
0文章
2瀏覽量
5847
發(fā)布評論請先 登錄
相關(guān)推薦
評論