<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 模擬技術(shù) > 計算法簡(jiǎn)單實(shí)現crc校驗

計算法簡(jiǎn)單實(shí)現crc校驗

——
作者:mumuyou 時(shí)間:2007-09-26 來(lái)源:PIC 單片機 收藏

  前一段時(shí)間做協(xié)議轉換器的時(shí)間用到CRC-16校驗,查了不少資料發(fā)現都不理想。查表法要建表太麻煩,而計算法覺(jué)得那些例子太羅嗦。最后只好自己寫(xiě)了,最后發(fā)現原來(lái)挺簡(jiǎn)單嘛:)

  兩個(gè)子程序搞定。這里用的多項式為:

  CRC-16    = X16 + X12 + X5 + X0 = 2^0+2^5+2^12+2^16=0x11021

  因最高位一定為“1”,故略去計算只采用0x1021即可

CRC_Byte:計算單字節的CRC值
CRC_Data:計算一幀數據的CRC值
CRC_High  CRC_Low:存放單字節CRC值
CRC16_High  CRC16_Low:存放幀數據CRC值

;<>-------------------------------------------------------------
;      Function:       CRC one byte
;      Input:             CRCByte
;      Output:           CRC_High CRC_Low
;<>-------------------------------------------------------------

CRC_Byte:
       clrf         CRC_Low
       clrf         CRC_High
       movlw           09H
       movwf           v_Loop1
       movf              CRCByte, w
       movwf           CRC_High
CRC:
       decfsz            v_Loop1                              ;8次循環(huán),每一位相應計算
       goto        CRC10
       goto        CRCend
CRC10
       bcf                STATUS, C
       rlf                  CRC_Low
       rlf                  CRC_High
       
       btfss              STATUS, C
       goto        CRC                                          ;為0不需計算
       movlw           10H                                    ;若多項式改變,這里作相應變化
       xorwf            CRC_High, f
       movlw           21H                                    ;若多項式改變,這里作相應變化
       xorwf            CRC_Low, f
       goto        CRC
CRCend:
       nop
       nop
       return {{分頁(yè)}}
;<>-------------------------------------------------------------
;      CRC one byte end
;<>-------------------------------------------------------------
;<>-------------------------------------------------------------
;      Function:       CRC date
;      Input:             BufStart(A,B,C)(一幀數據的起始地址) v_Count (要做CRC的字節數)
;      Output:           CRC16_High CRC16_Low(結果)
;<>-------------------------------------------------------------
CRC_Data:

       clrf         CRC16_High
       clrf         CRC16_Low

CRC_Data10

       movf              INDF, w
       xorwf            CRC16_High,w

       movwf           CRCByte
       call         CRC_Byte
       incf         FSR
       decf        v_Count                       ;需計算的字節數
       
       movf              CRC_High, w
       xorwf            CRC16_Low, w
       movwf           CRC16_High

       movf              CRC_Low, w
       movwf           CRC16_Low

       movf              v_Count, w                                          ;計算結束?
       btfss              STATUS, Z
       goto        CRC_Data10

       return

;<>-------------------------------------------------------------
;             CRC date end
;<>-------------------------------------------------------------

說(shuō)明: CRC 的計算原理如下(一個(gè)字節的簡(jiǎn)單例子)
    11011000 00000000 00000000  <- 一個(gè)字節數據, 左移 16b
   ^10001000 00010000 1         <- CRC-CCITT 多項式, 17b
    --------------------------
     1010000 00010000 10        <- 中間余數
    ^1000100 00001000 01
     -------------------------
       10100 00011000 1100
      ^10001 00000010 0001
       -----------------------
         101 00011010 110100
        ^100 01000000 100001
         ---------------------
           1 01011010 01010100
          ^1 00010000 00100001
           -------------------
             01001010 01110101  <- 16b CRC

仿此,可推出兩個(gè)字節數據計算如下:d 為數據,p 為項式,a 為余數
    dddddddd dddddddd 00000000 00000000 <- 數據 D ( D1, D0, 0, 0 )
   ^pppppppp pppppppp p                 <- 多項式 P
    -----------------------------------
    ...
             aaaaaaaa aaaaaaaa 0        <- 第一次的余數 A’ ( A’1, A’0 )
            ^pppppppp pppppppp p
             --------------------------
             ...
                      aaaaaaaa aaaaaaaa <- 結果 A ( A1, A0 )

由此與一字節的情況比較,將兩個(gè)字節分開(kāi)計算如下:
先算高字節:
    dddddddd 00000000 00000000 00000000 <- D1, 0, 0, 0
   ^pppppppp pppppppp p                 <- P
    -----------------------------------
    ...
             aaaaaaaa aaaaaaaa          <- 高字節部分余數 PHA1, PHA0

此處的部分余數與前面兩字節算法中的第一次余數有如下關(guān)系,即 A’1 = PHA1 ^ D0, A’0 = PHA0:
             aaaaaaaa aaaaaaaa          <- PHA1, PHA0
            ^dddddddd                   <- D0
             -----------------
             aaaaaaaa aaaaaaaa          <- A’1, A’0 {{分頁(yè)}}

低字節的計算:
             aaaaaaaa 00000000 00000000 <- A’1, 0, 0
            ^pppppppp pppppppp p        <- P
             --------------------------
             ...
                      aaaaaaaa aaaaaaaa <- 低字節部分余數 PLA1, PLA0
                     ^aaaaaaaa          <- A’0 , 即 PHA0
                      -----------------
                      aaaaaaaa aaaaaaaa <- 最后的 CRC ( A1, A0 )

總結以上內容可得規律如下:
設部分余數函數
    PA = f( d )
其中 d 為一個(gè)字節的數據(注意,除非 n = 0 ,否則就不是原始數據,見(jiàn)下文)
第 n 次的部分余數
    PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( d )
其中的
    d = ( PA( n - 1 ) >> 8 ) ^ D( n )
其中的 D( n ) 才是一個(gè)字節的原始數據。

公式如下:
    PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( ( PA( n - 1 ) >> 8 ) ^ D( n ) )

  可以注意到函數 f( d ) 的參數 d 為一個(gè)字節,對一個(gè)確定的多項式 P, f( d ) 的返回值 是與 d 一一對應的,總數為 256 項,將這些數據預先算出保存在表里,f( d )就轉換為一 個(gè)查表的過(guò)程,速度也就可以大幅提高,這也就是查表法計算 CRC 的原理。

  再來(lái)看 CRC 表是如何計算出來(lái)的,即函數 f( d ) 的實(shí)現方法。分析前面一個(gè)字節數據的 計算過(guò)程可發(fā)現,d 對結果的影響只表現為對 P 的移位異或,看計算過(guò)程中的三個(gè) 8 位 的列中只低兩個(gè)字節的最后結果是余數,而數據所在的高 8 位列最后都被消去了,因其 中的運算均為異或,不產(chǎn)生進(jìn)位或借位,故每一位數據只影響本列的結果,即 d 并不直接 影響結果。再將前例變化一下重列如下:
    11011000
    --------------------------
    10001000 00010000 1        // P
   ^ 1000100 00001000 01       // P
   ^  000000 00000000 000      // 0
   ^   10001 00000010 0001     // P
   ^    0000 00000000 00000    // 0
   ^     100 01000000 100001   // P
   ^      00 00000000 0000000  // 0
   ^       1 00010000 00100001 // P
           -------------------
             01001010 01110101

  現在的問(wèn)題就是如何根據 d 來(lái)對 P 移位異或了,從上面的例子看,也可以理解為每步 移位,但根據 d 決定中間余數是否與 P 異或。從前面原來(lái)的例子可以看出,決定的條件是中間余數的最高位為0,因為 P 的最高位一定為1,即當中間余數與 d 相應位異或的最高位為1時(shí),中間余數移位就要和 P 異或,否則只需移位即可。其方法如下例(上例的變形,注意其中空格的移動(dòng)表現了 d 的影響如何被排除在結果之外):

    d --------a--------
    1 00000000 00000000 <- HSB = 1
      0000000 000000000 <- a <<= 1
      0001000 000100001 <-不含最高位的 1
      -----------------
    1 0001000 000100001
      001000 0001000010
      000100 0000100001
      -----------------
    0 001100 0001100011 <- HSB = 0
      01100 00011000110
      -----------------
    1 01100 00011000110 <- HSB = 1
      1100 000110001100
      0001 000000100001
      -----------------
    1 1101 000110101101 <- HSB = 0
      101 0001101011010
      -----------------
    0 101 0001101011010 <- HSB = 1
      01 00011010110100
      00 01000000100001
      -----------------
    0 01 01011010010101 <- HSB = 0
      1 010110100101010
      -----------------
    0 1 010110100101010 <- HSB = 1
       0101101001010100
       0001000000100001
      -----------------
       0100101001110101 <- CRC

  結合這些,前面的程序就好理解了。



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>