電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 9|回復(fù): 0
收起左側(cè)

嵌入式設(shè)備經(jīng)常用 CRC 校驗(yàn),它的實(shí)現(xiàn)原理是這樣的。

[復(fù)制鏈接]

485

主題

485

帖子

1623

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
1623
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-12-12 12:01:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師
* F2 D; W) {- T關(guān)注我,一起變得更加優(yōu)秀!& R2 G( `! H0 L+ D  ~+ t3 T0 i1 n
4 @9 X. C( ^3 y& s6 D5 V, i+ M7 n
一、CRC校驗(yàn)介紹
, u* x1 V7 s4 C$ Z7 i- l  B+ ~

& s: X) N, z, G# Z循環(huán)冗余校驗(yàn)碼(CRC),是一種常用的、具有檢錯(cuò)、糾錯(cuò)能力的校驗(yàn)碼,在早期的通信中運(yùn)用廣泛。循環(huán)冗余校驗(yàn)碼常用于外存儲(chǔ)器和計(jì)算機(jī)同步通信的數(shù)據(jù)校驗(yàn)。循環(huán)冗余校驗(yàn)是通過某種數(shù)學(xué)運(yùn)算來建立數(shù)據(jù)位和校驗(yàn)位的約定關(guān)系的。5 W& a- U  Q/ f, S, w
, W2 z) R0 p5 D* h* V/ k
與奇偶校驗(yàn)、和校驗(yàn)、異或校驗(yàn)等校驗(yàn)方式不同,CRC校驗(yàn)的計(jì)算過程相對(duì)復(fù)雜很多。
1 `! S  p2 b5 R9 ]+ G0 g4 s+ r+ D' v+ T9 N; B
二、模2除法介紹
4 D6 }/ g8 }7 N. L, t1 @0 ^) l
/ v7 _1 E6 ~- ?' {7 [6 i  _+ {7 k0 O
CRC校驗(yàn)原理雖然看起來比較復(fù)雜,其實(shí)也不難理解,其根本思想就是先在要發(fā)送的幀后面附加一個(gè)數(shù),生成一個(gè)新幀發(fā)送給接收端。當(dāng)然,這個(gè)附加的數(shù)不是隨意的,它要使所生成的新幀能與發(fā)送端和接收端共同選定的某個(gè)特定數(shù)整除。  A! x! l: r+ A7 d5 D( Q
這里不是直接采用二進(jìn)制除法,而是采用一種稱之為“模2除法”。到達(dá)接收端后,再把接收到的新幀除以(同樣采用“模2除法”)這個(gè)選定的除數(shù)。因?yàn)樵诎l(fā)送端發(fā)送數(shù)據(jù)幀之前就已通過附加一個(gè)數(shù),做了“去余”處理,所以結(jié)果應(yīng)該是沒有余數(shù),結(jié)果能夠被除數(shù)整除。如果有余數(shù),則表明該幀在傳輸過程中出現(xiàn)了差錯(cuò)。. y3 \6 @+ E/ f" [! e
這里,為了能夠?qū)RC校驗(yàn)有深入了解,我們來介紹一下模2除法。與“算術(shù)除法”類似,但它既不向上位借位,也不比較除數(shù)和被除數(shù)的相同位數(shù)值的大小,只要以相同位數(shù)進(jìn)行相除即可。模2減法運(yùn)算實(shí)際上是按位異或運(yùn)算。也就是比較后,兩者對(duì)應(yīng)位相同則結(jié)果為“0”,不同則結(jié)果為“1”。如下圖所示,二進(jìn)制的數(shù)1010101除以1001,結(jié)果得到商為1011,余數(shù)為110。8 B" x; _8 r" m. |. H/ @% Q

) a' P. s9 y7 Z6 h, O: a* r2 j/ |* Z* \
三、CRC校驗(yàn)原理8 C! ]+ ]4 c0 {3 ~5 U2 c& M2 n" K

% }& D, s/ A! r8 j9 m  Z3 j上面我們對(duì)CRC校驗(yàn)進(jìn)行了簡單介紹,下面我們就來看看CRC校驗(yàn)是如何實(shí)現(xiàn)的。! I6 o9 u6 p) l' O1 s1 K) l
! @$ L8 w5 V/ {8 Q6 t  |" j
首先,為了進(jìn)行CRC校驗(yàn),發(fā)送端和接收端要約定一個(gè)除數(shù),這個(gè)除數(shù)通常是以多項(xiàng)方式表示,這個(gè)多項(xiàng)式也稱之為“生成多項(xiàng)式”。如常用的多項(xiàng)式x4 + x + 1,表示的除數(shù)為10011,多項(xiàng)式x16 + x15 + x2 + 1表示的除數(shù)為11000000000000101,下表列出了常用的除數(shù)多項(xiàng)式公式。1 \. F- b2 B5 t9 @1 A
: V4 s% S! s! I' q) F* q- p
- Z; ~, B0 y0 L% ^9 z/ E" N
+ W" W2 ~+ `" Z* Y6 T: e5 W
選定了除數(shù)之后,需要在要發(fā)送的數(shù)據(jù)后面加上k-1位“0”,k為除數(shù)的位數(shù)。然后以這個(gè)加了k-1個(gè)“0“的新數(shù)(一共是m+k-1位)以“模2除法”方式除以上面這個(gè)除數(shù),所得到的余數(shù)就是這個(gè)數(shù)據(jù)的CRC校驗(yàn)碼。但要注意的是,余數(shù)的位數(shù)一定要是比除數(shù)位數(shù)只能少一位,即使前面位是0,甚至是全為0(附帶好整除時(shí))也都不能省略。
5 a1 j/ p2 y  W, a/ C; I最后,再把這個(gè)校驗(yàn)碼附加在原數(shù)據(jù)后面,構(gòu)建一個(gè)新幀發(fā)送到接收端;最后在接收端再把這個(gè)新幀以“模2除法”方式除以前面選擇的除數(shù),如果沒有余數(shù),則表明該幀在傳輸過程中沒出錯(cuò),否則出現(xiàn)了差錯(cuò)。
0 q7 w* b6 t7 @9 D2 i) }  M4 }8 m9 f: ^! X! c$ L$ R/ G" V& N
下面,我們通過一個(gè)例子來說明一下,CRC校驗(yàn)的計(jì)算過程。
. g  [+ X- b2 l5 `" Q2 ]7 e6 `( b0 T. Z" h" \+ M, J
假設(shè)我們計(jì)算十六進(jìn)制數(shù)0xBB的CRC校驗(yàn)碼,我們使用的生成多項(xiàng)式為x4 + x + 1。則待計(jì)算的數(shù)表示為二進(jìn)制位1011 1011,除數(shù)為10011。由于生成多項(xiàng)式的位數(shù)為5,根據(jù)上面的介紹,得知CRC校驗(yàn)碼的位數(shù)為4(校驗(yàn)碼的位數(shù)比生成多項(xiàng)式的位數(shù)少1)。因此在原始數(shù)據(jù)后面再加4個(gè)0,得到1011 1011 0000,然后把這個(gè)數(shù)以“模2除法”方式除以生成多項(xiàng)式,得到的余數(shù)(即CRC碼)為1111,如下圖所示。, K! Y& B( \) \+ ]1 T8 Y% D

5 y/ i; J! g# O# I把上步計(jì)算得到的CRC校驗(yàn)1111替換原始幀1011 1011 0000后面的四個(gè)“0”,得到新幀1011 1011 1111。再把這個(gè)新幀發(fā)送到接收端。當(dāng)以上新幀到達(dá)接收端后,接收端會(huì)把這個(gè)新幀再用上面選定的除數(shù)10011以“模2除法”方式去除,驗(yàn)證余數(shù)是否為0,如果為0,則證明該幀數(shù)據(jù)在傳輸過程中沒有出現(xiàn)差錯(cuò),否則出現(xiàn)了差錯(cuò)。
1 ]7 y8 q7 u3 R7 M* r四、CRC校驗(yàn)的c代碼實(shí)現(xiàn)
9 _* ~: x3 J' Z

1 _. H2 c1 `6 C  [CRC校驗(yàn)的計(jì)算過程比較復(fù)雜,一般代碼實(shí)現(xiàn)采用查表的方法。下面的代碼是CRC16校驗(yàn)實(shí)現(xiàn)的代碼,對(duì)應(yīng)的CRC算法為CRC-16/MODBUS,生成多項(xiàng)式為x16 + x15 + x2 + 1。注意:示例代碼得到的CRC結(jié)果中,高8位在前,低8位在后。需要根據(jù)具體的應(yīng)用場景進(jìn)行調(diào)整。
  • #include  const unsigned char chCRCHTalbe[] = //CRC高位字節(jié)值表{0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40}; const unsigned char chCRCLTalbe[] = //CRC低位字節(jié)值表{0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,0x41, 0x81, 0x80, 0x40}; unsigned short CRC16(unsigned char* pchMsg, unsigned short wDataLen){  unsigned char chCRCHi = 0xFF; // 高CRC字節(jié)初始化  unsigned char chCRCLo = 0xFF; // 低CRC字節(jié)初始化  unsigned short wIndex; // CRC循環(huán)中的索引   while(wDataLen--)  {    // 計(jì)算CRC    wIndex = chCRCLo ^ *pchMsg++ ;    chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];    chCRCHi = chCRCLTalbe[wIndex] ;  }   return((chCRCHi 8) | chCRCLo) ;} void main(){  unsigned char data[]={1,2,3,4,5,6};   unsigned short result;   result = CRC16(data,6);   printf("%X",result);}5 ^$ }/ p3 G# C! m, ^: K" h, _
    原文:https://blog.csdn.net/bhniunan/article/details/111031467. Q- @% C- s: M
    3 b. ^4 v* L, v  j. |; j4 n
    -END-
    8 M8 O9 S& i0 i  a  y往期推薦:點(diǎn)擊圖片即可跳轉(zhuǎn)閱讀+ R$ g) T1 e* L

    & Q2 |1 U% b9 K6 Z  d                                                        6 v! l4 m! G9 D/ o) Q  i; U4 _! x
                                                                    9 i" J8 W, p, I. s5 O- X
                                                                            1 u' G- W& m& ~9 U6 k
                                                                                   
      s1 I1 j4 P* m5 a
    1 y0 S/ Y, V. P6 B) D4 _                                                                               
    ) G, l* W: v( ~; q( U1 b- N6 \                                                                                        掌握這些嵌入式 C/C++ 開發(fā)神器,迅速提升開發(fā)效率!( {: U4 w1 O4 g; x5 _- w
                                                                                   
    6 {5 [4 b2 k5 o5 I7 g                                                                       
    " f: J2 K% y4 X                                                                0 k1 f, ]: V' d) v6 o& h1 |7 U3 v/ o
                                                           
    0 C# ^, B: A5 B3 v/ g* v7 w8 a$ F                                                ; o0 A- X3 A$ S' i
    # h4 K2 s/ Q, T! e" W$ @
                                                           
    ! @8 r* B+ H1 [$ L0 Q: |                                                                / U! w# c  t/ q) o. x# q0 W' F1 C
                                                                           
    & x5 l, z: V+ M, A/ ?                                                                               
    8 |( I$ x6 C$ E! c' r- r% P/ q
    ! s; a# \5 a0 I: b+ k+ G2 A5 K7 q                                                                                , y4 y! O; s' x6 H! ^# L
                                                                                            搞懂這幾個(gè)常見的嵌入式軟件架構(gòu),足夠平時(shí)開發(fā)使用了!
    ; p% P/ j7 A6 _                                                                               
    ; a3 ^# j% s6 @2 W; ?9 q1 ~                                                                        ( C% g, V) T2 n: A, w& K
                                                                   
    ) r% S) M6 r' r5 L; v9 ]0 }. F( V                                                       
    3 e7 Y3 m+ i: U2 Y" T6 L                                                ! M: @7 r! t" g. c# Q

    3 ~# @) ?' w" \: q$ y                                                        ( [* A; E0 h) }( l" b1 w+ P
                                                                   
    , e& B7 o1 {6 |: e8 M  |                                                                       
    # T' r* Z* }5 N3 h6 b( m                                                                                1 G& C$ z' ~' P$ a3 u1 X: M% T
    - m+ s6 a; V8 z7 o" a6 Y
                                                                                   
    8 I! F. v( ]3 m4 r7 e                                                                                        工程師的藝術(shù),完美治愈強(qiáng)迫癥!4 z3 v# M; p0 ?
                                                                                   
    5 y# N# F( i7 P$ A8 i; S                                                                       
    $ l. S2 K$ o7 O3 c1 P( _; r2 ~                                                                - {: ?- P' c  n2 M* g1 p- O( j
                                                            0 J" B( z( X" N8 Y
                                                    + @, F1 k: ^4 H, U( B" V+ F
    我是老溫,一名熱愛學(xué)習(xí)的嵌入式工程師! C) I/ P% O/ V/ Z& n
    關(guān)注我,一起變得更加優(yōu)秀!
    . f+ G: H& B: d& o
  • 發(fā)表回復(fù)

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表