<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文講透CRC校驗(yàn)碼-附贈(zèng)C語言實(shí)例

          共 13684字,需瀏覽 28分鐘

           ·

          2021-07-15 18:14

          5b069e37f46493453b380afb1b5defd6.webp

          最近工作用到CRC校驗(yàn),順便整理本篇文章和大家一起研究。

          一、CRC概念

          1. 什么是CRC?

          CRC(Cyclic Redundancy Checksum)是一種糾錯(cuò)技術(shù),代表循環(huán)冗余校驗(yàn)和。

          數(shù)據(jù)通信領(lǐng)域中最常用的一種差錯(cuò)校驗(yàn)碼,其信息字段和校驗(yàn)字段長度可以任意指定,但要求通信雙方定義的CRC標(biāo)準(zhǔn)一致。主要用來檢測或校驗(yàn)數(shù)據(jù)傳輸或者保存后可能出現(xiàn)的錯(cuò)誤。它的使用方式可以說明如下圖所示:

          在數(shù)據(jù)傳輸過程中,無論傳輸系統(tǒng)的設(shè)計(jì)再怎么完美,差錯(cuò)總會(huì)存在,這種差錯(cuò)可能會(huì)導(dǎo)致在鏈路上傳輸?shù)囊粋€(gè)或者多個(gè)幀被破壞(出現(xiàn)比特差錯(cuò),0變?yōu)?,或者1變?yōu)?),從而接受方接收到錯(cuò)誤的數(shù)據(jù)。

          為盡量提高接受方收到數(shù)據(jù)的正確率,在接收方接收數(shù)據(jù)之前需要對數(shù)據(jù)進(jìn)行差錯(cuò)檢測,當(dāng)且僅當(dāng)檢測的結(jié)果為正確時(shí)接收方才真正收下數(shù)據(jù)。檢測的方式有多種,常見的有奇偶校驗(yàn)因特網(wǎng)校驗(yàn)循環(huán)冗余校驗(yàn)等。

          2. 使用方法概述

          循環(huán)冗余校驗(yàn)是一種用于校驗(yàn)通信鏈路上數(shù)字傳輸準(zhǔn)確性的計(jì)算方法(通過某種數(shù)學(xué)運(yùn)算來建立數(shù)據(jù)位和校驗(yàn)位的約定關(guān)系的 )。b7fe107c4cf958494bf6946f05f660d2.webp

          發(fā)送方計(jì)算機(jī)使用某公式計(jì)算出被傳送數(shù)據(jù)所含信息的一個(gè)值,并將此值 附在被傳送數(shù)據(jù)后,接收方計(jì)算機(jī)則對同一數(shù)據(jù)進(jìn)行 相同的計(jì)算,應(yīng)該得到相同的結(jié)果。

          如果這兩個(gè) CRC結(jié)果不一致,則說明發(fā)送中出現(xiàn)了差錯(cuò),接收方計(jì)算機(jī)可要求發(fā)送方計(jì)算機(jī)重新發(fā)送該數(shù)據(jù)。

          3. 應(yīng)用廣泛

          在諸多檢錯(cuò)手段中,CRC是最著名的一種。CRC的全稱是循環(huán)冗余校驗(yàn),其特點(diǎn)是:檢錯(cuò)能力強(qiáng),開銷小,易于用編碼器及檢測電路實(shí)現(xiàn)。從其檢錯(cuò)能力來看,它所不能發(fā)現(xiàn)的錯(cuò)誤的幾率僅為0.0047%以下。

          從性能上和開銷上考慮,均遠(yuǎn)遠(yuǎn)優(yōu)于奇偶校驗(yàn)及算術(shù)和校驗(yàn)等方式。

          因而,在數(shù)據(jù)存儲(chǔ)和數(shù)據(jù)通訊領(lǐng)域,CRC無處不在:著名的通訊協(xié)議X.25的FCS(幀檢錯(cuò)序列)采用的是CRC-CCITT,WinRAR、NERO、ARJ、LHA等壓縮工具軟件采用的是CRC32,磁盤驅(qū)動(dòng)器的讀寫采用了CRC16,通用的圖像存儲(chǔ)格式GIF、TIFF等也都用CRC作為檢錯(cuò)手段。

          二、CRC名稱的定義

          這里需要知道幾個(gè)組成部分或者說計(jì)算概念:多項(xiàng)式公式、多項(xiàng)式簡記式、數(shù)據(jù)寬度、初始值、結(jié)果異或值、輸入值反轉(zhuǎn)、輸出值反轉(zhuǎn)、參數(shù)模型。

          1、多項(xiàng)式公式

          對于CRC標(biāo)準(zhǔn)除數(shù),一般使用多項(xiàng)式(或二項(xiàng)式)公式表示,如下圖中除數(shù)11011(poly值為0x1b)的二項(xiàng)式為G(X)=X4+X3+X+1,X的指數(shù)就代表了該bit位上的數(shù)據(jù)為1,(最低位為0)。

          這里特別注意一下位數(shù)問題,除數(shù)的位數(shù)為二項(xiàng)式最高次冪+1(4+1=5),這個(gè)很重要。

          abe5affb43efbcfe5731864217fa8401.webp

          2、多項(xiàng)式簡記式

          通過對CRC的基本了解我們知道,多項(xiàng)式的首尾必定為1,而這個(gè)1的位置在下一步計(jì)算一定為0,所以就把前面這個(gè)1給省略掉了,出現(xiàn)了一個(gè)叫簡記式的東西,如上例中除數(shù)11011的簡記式為1011,很多看過CRC高級語言源碼的人會(huì)知道,對于CRC_16標(biāo)準(zhǔn)下G(X)=X16+X15+X2+1(16#18005)的poly值實(shí)際上是8005,這里使用的就是簡記式。后面會(huì)對這個(gè)用法做一個(gè)說明。

          3、數(shù)據(jù)寬度

          數(shù)據(jù)寬度指的就是CRC校驗(yàn)碼的長度(二進(jìn)制位數(shù)),知道了CRC的運(yùn)算概念和多項(xiàng)式,就可以理解這個(gè)概念了,CRC長度始終要比除數(shù)位數(shù)少1,與簡記式長度是一致的。

          以上三個(gè)數(shù)據(jù)就是我們經(jīng)常能夠用到的基本數(shù)據(jù)

          4、初始值與結(jié)果異或值

          在一些標(biāo)準(zhǔn)中,規(guī)定了初始值,則數(shù)據(jù)在進(jìn)行上述二項(xiàng)式運(yùn)算之前,需要先將要計(jì)算的數(shù)據(jù)與初始值的最低字節(jié)進(jìn)行異或,然后再與多項(xiàng)式進(jìn)行計(jì)算。

          而在結(jié)果異或值不為零的情況下,則需要將計(jì)算得到的CRC結(jié)果值再與結(jié)果異或值進(jìn)行一次異或計(jì)算,得到的最終值才是我們需要的CRC校驗(yàn)碼。

          這里可以看出,初始值與結(jié)果值的位數(shù)要求與數(shù)據(jù)寬度一致。

          5、輸入值反轉(zhuǎn)與輸出值反轉(zhuǎn)

          輸入值反轉(zhuǎn)的意思是在計(jì)算之前先將二項(xiàng)式反轉(zhuǎn),然后再用得到的新值和數(shù)據(jù)進(jìn)行計(jì)算。如對于G(X)=X16+X15+X2+1(16#18005),其正向值為1 1000 0000 0000 0101,反轉(zhuǎn)值則為1010 0000 0000 0001 1

          輸出值反轉(zhuǎn)則是將最終得到的CRC結(jié)果反轉(zhuǎn)。

          通常,輸入值反轉(zhuǎn)后的結(jié)果值也會(huì)是反轉(zhuǎn)的,所以這兩個(gè)選項(xiàng)一般是同向的,我們只有在在線CRC計(jì)算器中會(huì)看到自由選擇正反轉(zhuǎn)的情況存在。

          三、常見的CRC算法

          雖然CRC可以任意定義二項(xiàng)式、數(shù)據(jù)長度等,但沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)的話,就會(huì)讓整個(gè)計(jì)算變得非常的麻煩。但實(shí)際上,不同的廠家經(jīng)常采用不同的標(biāo)準(zhǔn)算法,這里列出了一些國際常用的模型表:

          名稱多項(xiàng)式表示法應(yīng)用舉例
          CRC-8X8+X2+X+10X107
          CRC-12X12+X11+X3+X2+X+10X180Ftelecom systems
          CRC-16X16+X15+X2+10X18005Bisync, Modbus, USB, ANSI X3.28, SIA DC-07, many others; also known as CRC-16 and CRC-16-ANSI
          CRC-CCITTX16+X12+X5+10X11021ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
          CRC-32X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X+10x104C11DB7ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
          CRC-32CX32+X28+X27+X26+X25+X23+X22+X20+X19+X18+X14+X13+X11+X10+X9+X8+X6+10x11EDC6F41iSCSI, SCTP, G.hn payload, SSE4.2, Btrfs, ext4, Ceph

          四、CRC校驗(yàn)算法前置知識

          在學(xué)習(xí)CRC校驗(yàn)算法之前,先復(fù)習(xí)一下CRC會(huì)涉及的主要幾個(gè)主要的算法。

          1. 異或

          異或,就是不同為1,相同為0,運(yùn)算符號是^。

          0^0?=?0
          0^1?=?1
          1^1?=?0
          1^0?=?1

          異或運(yùn)算存在如下幾個(gè)規(guī)律,需要了解。

          0^x?=?x?即0?異或任何數(shù)等于任何數(shù)
          1^x?=?~x?即1異或任何數(shù)等于任何數(shù)取反
          x^x?=?0?即任何數(shù)與自己異或,結(jié)果為0
          a?^?b?=?b?^?a?交換律
          a?^?(b?^?c)?=?(a?^?b)?^c?結(jié)合律

          2. 模2加法

          模2加法相對于普通的算術(shù)加法,主要的區(qū)別在模2加法,不做進(jìn)位處理。具體結(jié)果如下。0+0 = 0 0+1 = 1 1+1 = 0 1+0 = 1 我們發(fā)現(xiàn)模2加法的計(jì)算結(jié)果,同異或運(yùn)算結(jié)果一模一樣。進(jìn)一步推演,我們會(huì)發(fā)現(xiàn),異或運(yùn)算的5個(gè)規(guī)律,同樣適合于模2加法。這里,就不在一一列舉了。

          3. 模2減法

          模2減法相對于普通的算術(shù)減法,主要的區(qū)別在模2減法,不做借位處理。具體結(jié)果如下。0-0 = 0 0-1 = 1 1-1 = 0 1-0 = 1 我們發(fā)現(xiàn)模2減法的計(jì)算結(jié)果,同模2加法,以及異或的運(yùn)算結(jié)果一模一樣。進(jìn)一步推演,我們會(huì)發(fā)現(xiàn),異或運(yùn)算的5個(gè)規(guī)律,同樣適合于模2減法。這里,就不在一一列舉了。

          4. 模2除法

          模2除法相對于普通的算術(shù)除法,主要的區(qū)別在模2除法,它既不向上位借位,也不比較除數(shù)和被除數(shù)的相同位數(shù)值的大小,只要以相同位數(shù)進(jìn)行相除即可。

          五、CRC原理

          CRC原理:在K位信息碼(目標(biāo)發(fā)送數(shù)據(jù))后再拼接R位校驗(yàn)碼,使整個(gè)編碼長度為N位,因此這種編碼也叫(N,K)碼。

          通俗的說,就是在需要發(fā)送的信息后面附加一個(gè)數(shù)(即校驗(yàn)碼),生成一個(gè)新的發(fā)送數(shù)據(jù)發(fā)送給接收端。這個(gè)數(shù)據(jù)要求能夠使生成的新數(shù)據(jù)被一個(gè)特定的數(shù)整除。這里的整除需要引入模 2除法的概念。

          那么,CRC校驗(yàn)的具體做法就是

          (1)選定一個(gè)標(biāo)準(zhǔn)除數(shù)(K位二進(jìn)制數(shù)據(jù)串)

          (2)在要發(fā)送的數(shù)據(jù)(m位)后面加上K-1位0,然后將這個(gè)新數(shù)(M+K-1位)以模2除法的方式除以上面這個(gè)標(biāo)準(zhǔn)除數(shù),所得到的余數(shù)也就是該數(shù)據(jù)的CRC校驗(yàn)碼(注:余數(shù)必須比除數(shù)少且只少一位,不夠就補(bǔ)0)

          (3)將這個(gè)校驗(yàn)碼附在原m位數(shù)據(jù)后面,構(gòu)成新的M+K-1位數(shù)據(jù),發(fā)送給接收端。

          (4)接收端將接收到的數(shù)據(jù)除以標(biāo)準(zhǔn)除數(shù),如果余數(shù)為0則認(rèn)為數(shù)據(jù)正確。

          注意:CRC校驗(yàn)中有兩個(gè)關(guān)鍵點(diǎn):

          一是要預(yù)先確定一個(gè)發(fā)送端和接收端都用來作為除數(shù)的二進(jìn)制比特串(或多項(xiàng)式);

          二是把原始幀與上面選定的除進(jìn)行二進(jìn)制除法運(yùn)算,計(jì)算出FCS。

          前者可以隨機(jī)選擇,也可按國際上通行的標(biāo)準(zhǔn)選擇,但最高位和最低位必須均為“1”

          六、循環(huán)冗余的計(jì)算

          實(shí)例:

          由于CRC-32、CRC-16、CCITT和CRC-4的編碼過程基本一致,只有位數(shù)和生成多項(xiàng)式不一樣,下面就舉例,來說明CRC校驗(yàn)碼生成過程。

          對于數(shù)據(jù)1110 0101(16#E5),以指定除數(shù)11011求它的CRC校驗(yàn)碼,其過程如下:35ef5cee557a7424fff86fb25740d2c7.webp

          使用上面計(jì)算的校驗(yàn)和和消息數(shù)據(jù),可以創(chuàng)建要傳輸?shù)拇a字。

          9f8bbb0715d8bd69ad95ebadc427b6ea.webp

          有時(shí)候,我們需要填充checksum到制定的位置,這就涉及到字節(jié)序問題,建議用memcpy()進(jìn)行拷貝。

          七、代碼實(shí)現(xiàn)

          實(shí)現(xiàn)算法參考網(wǎng)絡(luò)相關(guān)代碼,進(jìn)行整理并驗(yàn)證,可直接使用。crc.c

          /*??
          ?*一口Linux
          ?*2021.6.21
          ?*version:?1.0.0
          */

          #include?"crc.h"
          #include?<stdio.h>

          typedef?enum?{
          ?REF_4BIT?=?4,
          ?REF_5BIT?=?5,
          ?REF_6BIT?=?6,
          ?REF_7BIT?=?7,
          ?REF_8BIT?=?8,
          ?REF_16BIT?=?16,
          ?REF_32BIT?=?32
          }REFLECTED_MODE;

          uint32_t?ReflectedData(uint32_t?data,?REFLECTED_MODE?mode)
          {
          ?data?=?((data?&?0xffff0000)?>>?16)?|?((data?&?0x0000ffff)?<<?16);
          ?data?=?((data?&?0xff00ff00)?>>?8)?|?((data?&?0x00ff00ff)?<<?8);
          ?data?=?((data?&?0xf0f0f0f0)?>>?4)?|?((data?&?0x0f0f0f0f)?<<?4);
          ?data?=?((data?&?0xcccccccc)?>>?2)?|?((data?&?0x33333333)?<<?2);
          ?data?=?((data?&?0xaaaaaaaa)?>>?1)?|?((data?&?0x55555555)?<<?1);

          ?switch?(mode)
          ?{
          ?case?REF_32BIT:
          ??return?data;
          ?case?REF_16BIT:
          ??return?(data?>>?16)?&?0xffff;
          ?case?REF_8BIT:
          ??return?(data?>>?24)?&?0xff;
          ?case?REF_7BIT:
          ??return?(data?>>?25)?&?0x7f;
          ?case?REF_6BIT:
          ??return?(data?>>?26)?&?0x7f;
          ?case?REF_5BIT:
          ??return?(data?>>?27)?&?0x1f;
          ?case?REF_4BIT:
          ??return?(data?>>?28)?&?0x0f;
          ?}
          ?return?0;
          }

          uint8_t?CheckCrc4(uint8_t?poly,?uint8_t?init,?bool?refIn,?bool?refOut,?uint8_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint8_t?i;
          ?uint8_t?crc;

          ?if?(refIn?==?true)
          ?{
          ??crc?=?init;
          ??poly?=?ReflectedData(poly,?REF_4BIT);

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x01)
          ????{
          ?????crc?>>=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?>>=?1;
          ????}
          ???}
          ??}

          ??return?crc?^?xorOut;
          ?}
          ?else
          ?{
          ??crc?=?init?<<?4;
          ??poly?<<=?4;

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x80)
          ????{
          ?????crc?<<=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?<<=?1;
          ????}
          ???}
          ??}

          ??return?(crc?>>?4)?^?xorOut;
          ?}
          }

          uint8_t?CheckCrc5(uint8_t?poly,?uint8_t?init,?bool?refIn,?bool?refOut,?uint8_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint8_t?i;
          ?uint8_t?crc;

          ?if?(refIn?==?true)
          ?{
          ??crc?=?init;
          ??poly?=?ReflectedData(poly,?REF_5BIT);

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x01)
          ????{
          ?????crc?>>=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?>>=?1;
          ????}
          ???}
          ??}

          ??return?crc?^?xorOut;
          ?}
          ?else
          ?{
          ??crc?=?init?<<?3;
          ??poly?<<=?3;

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x80)
          ????{
          ?????crc?<<=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?<<=?1;
          ????}
          ???}
          ??}

          ??return?(crc?>>?3)?^?xorOut;
          ?}
          }

          uint8_t?CheckCrc6(uint8_t?poly,?uint8_t?init,?bool?refIn,?bool?refOut,?uint8_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint8_t?i;
          ?uint8_t?crc;

          ?if?(refIn?==?true)
          ?{
          ??crc?=?init;
          ??poly?=?ReflectedData(poly,?REF_6BIT);

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x01)
          ????{
          ?????crc?>>=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?>>=?1;
          ????}
          ???}
          ??}

          ??return?crc?^?xorOut;
          ?}
          ?else
          ?{
          ??crc?=?init?<<?2;
          ??poly?<<=?2;

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x80)
          ????{
          ?????crc?<<=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?<<=?1;
          ????}
          ???}
          ??}

          ??return?(crc?>>?2)?^?xorOut;
          ?}
          }

          uint8_t?CheckCrc7(uint8_t?poly,?uint8_t?init,?bool?refIn,?bool?refOut,?uint8_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint8_t?i;
          ?uint8_t?crc;

          ?if?(refIn?==?true)
          ?{
          ??crc?=?init;
          ??poly?=?ReflectedData(poly,?REF_7BIT);

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x01)
          ????{
          ?????crc?>>=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?>>=?1;
          ????}
          ???}
          ??}

          ??return?crc?^?xorOut;
          ?}
          ?else
          ?{
          ??crc?=?init?<<?1;
          ??poly?<<=?1;

          ??while?(length--)
          ??{
          ???crc?^=?*buffer++;
          ???for?(i?=?0;?i?<?8;?i++)
          ???{
          ????if?(crc?&?0x80)
          ????{
          ?????crc?<<=?1;
          ?????crc?^=?poly;
          ????}
          ????else
          ????{
          ?????crc?<<=?1;
          ????}
          ???}
          ??}

          ??return?(crc?>>?1)?^?xorOut;
          ?}
          }

          uint8_t?CheckCrc8(uint8_t?poly,?uint8_t?init,?bool?refIn,?bool?refOut,?uint8_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint32_t?i?=?0;
          ?uint8_t?crc?=?init;

          ?while?(length--)
          ?{
          ??if?(refIn?==?true)
          ??{
          ???crc?^=?ReflectedData(*buffer++,?REF_8BIT);
          ??}
          ??else
          ??{
          ???crc?^=?*buffer++;
          ??}

          ??for?(i?=?0;?i?<?8;?i++)
          ??{
          ???if?(crc?&?0x80)
          ???{
          ????crc?<<=?1;
          ????crc?^=?poly;
          ???}
          ???else
          ???{
          ????crc?<<=?1;
          ???}
          ??}
          ?}

          ?if?(refOut?==?true)
          ?{
          ??crc?=?ReflectedData(crc,?REF_8BIT);
          ?}

          ?return?crc?^?xorOut;
          }

          uint16_t?CheckCrc16(uint16_t?poly,?uint16_t?init,?bool?refIn,?bool?refOut,?uint16_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint32_t?i?=?0;
          ?uint16_t?crc?=?init;

          ?while?(length--)
          ?{
          ??if?(refIn?==?true)
          ??{
          ???crc?^=?ReflectedData(*buffer++,?REF_8BIT)?<<?8;
          ??}
          ??else
          ??{
          ???crc?^=?(*buffer++)?<<?8;
          ??}

          ??for?(i?=?0;?i?<?8;?i++)
          ??{
          ???if?(crc?&?0x8000)
          ???{
          ????crc?<<=?1;
          ????crc?^=?poly;
          ???}
          ???else
          ???{
          ????crc?<<=?1;
          ???}
          ??}
          ?}

          ?if?(refOut?==?true)
          ?{
          ??crc?=?ReflectedData(crc,?REF_16BIT);
          ?}

          ?return?crc?^?xorOut;
          }

          uint32_t?CheckCrc32(uint32_t?poly,?uint32_t?init,?bool?refIn,?bool?refOut,?uint32_t?xorOut,
          ?const?uint8_t?*buffer,?uint32_t?length)

          {
          ?uint32_t?i?=?0;
          ?uint32_t?crc?=?init;

          ?while?(length--)
          ?{
          ??if?(refIn?==?true)
          ??{
          ???crc?^=?ReflectedData(*buffer++,?REF_8BIT)?<<?24;
          ??}
          ??else
          ??{
          ???crc?^=?(*buffer++)?<<?24;
          ??}

          ??for?(i?=?0;?i?<?8;?i++)
          ??{
          ???if?(crc?&?0x80000000)
          ???{
          ????crc?<<=?1;
          ????crc?^=?poly;
          ???}
          ???else
          ???{
          ????crc?<<=?1;
          ???}
          ??}
          ?}

          ?if?(refOut?==?true)
          ?{
          ??crc?=?ReflectedData(crc,?REF_32BIT);
          ?}

          ?return?crc?^?xorOut;
          }

          uint32_t?CrcCheck(CRC_Type?crcType,?const?uint8_t?*buffer,?uint32_t?length)
          {
          ?switch?(crcType.width)
          ?{
          ?case?4:
          ??return?CheckCrc4(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?5:
          ??return?CheckCrc5(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?6:
          ??return?CheckCrc6(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?7:
          ??return?CheckCrc7(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?8:
          ??return?CheckCrc8(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?16:
          ??return?CheckCrc16(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?case?32:
          ??return?CheckCrc32(crcType.poly,?crcType.init,?crcType.refIn,?crcType.refOut,
          ???crcType.xorOut,?buffer,?length);
          ?}
          ?return?0;
          }

          crc.h

          /*??
          ?*一口Linux
          ?*2021.6.21
          ?*version:?1.0.0
          */

          #ifndef?__CRC_H__
          #define?__CRC_H__

          #include?<stdint.h>
          #include?<stdbool.h>

          typedef?struct?{
          ?uint8_t?width;
          ?uint32_t?poly;
          ?uint32_t?init;
          ?bool?refIn;
          ?bool?refOut;
          ?uint32_t?xorOut;
          }CRC_Type;

          uint32_t?CrcCheck(CRC_Type?crcType,?const?uint8_t?*buffer,?uint32_t?length);

          #endif

          main.c

          /*??
          ?*一口Linux
          ?*2021.6.21
          ?*version:?1.0.0
          */

          #include?<stdio.h>
          #include?<stdint.h>
          #include?<stdbool.h>
          #include?"crc.h"

          #define?LENGTH?8
          const?uint8_t?data[3][LENGTH]?=?{
          ?{?0x01,?0x02,?0x03,?0x04,?0x05,?0x06,?0x07,?0x08?},
          ?{?0x01,?0x02,?0x04,?0x08,?0x10,?0x20,?0x40,?0x80?},
          ?{?0xfe,?0xfd,?0xfb,?0xf7,?0xef,?0xdf,?0xbf,?0x7f?}};

          typedef?struct?{
          ?CRC_Type?crcType;
          ?uint32_t?result[3];
          }CRC_Test;

          CRC_Test?crc4_ITU?=?{?{?4,?0x03,?0x00,?true,?true,?0x00?},?{?0x0f,?0x0a,?0x0e?}?};
          CRC_Test?crc5_EPC?=?{?{?5,?0x09,?0x09,?false,?false,?0x00?},?{?0x00,?0x0c,?0x17?}?};
          CRC_Test?crc5_ITU?=?{?{?5,?0x15,?0x00,?true,?true,?0x00?},?{?0x16,?0x0a,?0x17?}?};
          CRC_Test?crc5_USB?=?{?{?5,?0x05,?0x1f,?true,?true,?0x1f?},?{?0x10,?0x09,?0x17?}?};
          CRC_Test?crc6_ITU?=?{?{?6,?0x03,?0x00,?true,?true,?0x00?},?{?0x1d,?0x30,?0x00?}?};
          CRC_Test?crc7_MMC?=?{?{?7,?0x09,?0x00,?false,?false,?0x00?},?{?0x57,?0x30,?0x5b?}?};
          CRC_Test?crc8?=?{?{?8,?0x07,?0x00,?false,?false,?0x00?},?{?0x3e,?0xe1,?0x36?}?};
          CRC_Test?crc8_ITU?=?{?{?8,?0x07,?0x00,?false,?false,?0x55?},?{?0x6b,?0xb4,?0x63?}?};
          CRC_Test?crc8_ROHC?=?{?{?8,?0x07,?0xff,?true,?true,?0x00?},?{?0x6b,?0x78,?0x93?}?};
          CRC_Test?crc8_MAXIM?=?{?{?8,?0x31,?0x00,?true,?true,?0x00?},?{?0x83,?0x60,?0xa9?}?};
          CRC_Test?crc16_IBM?=?{?{?16,?0x8005,?0x0000,?true,?true,?0x0000?},?{?0xc4f0,?0x2337,?0xa776?}?};
          CRC_Test?crc16_MAXIM?=?{?{?16,?0x8005,?0x0000,?true,?true,?0xffff?},?{?0x3b0f,?0xdcc8,?0x5889?}?};
          CRC_Test?crc16_USB?=?{?{?16,?0x8005,?0xffff,?true,?true,?0xffff?},?{?0x304f,?0xd788,?0x53c9?}?};
          CRC_Test?crc16_MODBUS?=?{?{?16,?0x8005,?0xffff,?true,?true,?0x0000?},?{?0xcfb0,?0x2877,?0xac36?}?};
          CRC_Test?crc16_CCITT?=?{?{?16,?0x1021,?0x0000,?true,?true,?0x0000?},?{?0xeea7,?0xfe7c,?0x7919?}?};
          CRC_Test?crc16_CCITT_FALSE?=?{?{?16,?0x1021,?0xffff,?false,?false,?0x0000?},?{?0x4792,?0x13a7,?0xb546?}?};
          CRC_Test?crc16_X25?=?{?{?16,?0x1021,?0xffff,?true,?true,?0xffff?},?{?0x6dd5,?0x7d0f,?0xfa6a?}?};
          CRC_Test?crc16_XMODEM?=?{?{?16,?0x1021,?0x0000,?false,?false,?0x0000?},?{?0x76ac,?0x2299,?0x8478?}?};
          CRC_Test?crc16_DNP?=?{?{?16,?0x3D65,?0x0000,?true,?true,?0xffff?},?{?0x7bda,?0x0535,?0x08c4?}?};
          CRC_Test?crc32?=?{?{?32,?0x04c11db7,?0xffffffff,?true,?true,?0xffffffff?},?{?0x3fca88c5,?0xe0631a53,?0xa4051a26?}?};
          CRC_Test?crc32_MPEG2?=?{?{?32,?0x4c11db7,?0xffffffff,?false,?false,?0x00000000?},?{?0x14dbbdd8,?0x6509b4b6,?0xcb09d294?}?};

          void?CrcTest(CRC_Test?crcTest)
          {
          ?uint32_t?i;
          ?for?(i?=?0;?i?<?3;?i++)
          ?{
          ??printf("%08x\t%08x\r\n",?CrcCheck(crcTest.crcType,?data[i],?LENGTH),?crcTest.result[i]);
          ?}
          ?printf("\r\n");
          }

          int?main(void)
          {
          ?CrcTest(crc4_ITU);
          ?CrcTest(crc5_EPC);
          ?CrcTest(crc5_ITU);
          ?CrcTest(crc5_USB);
          ?CrcTest(crc6_ITU);
          ?CrcTest(crc7_MMC);
          ?CrcTest(crc8);
          ?CrcTest(crc8_ITU);
          ?CrcTest(crc8_ROHC);
          ?CrcTest(crc8_MAXIM);
          ?CrcTest(crc16_IBM);
          ?CrcTest(crc16_MAXIM);
          ?CrcTest(crc16_USB);
          ?CrcTest(crc16_MODBUS);
          ?CrcTest(crc16_CCITT);
          ?CrcTest(crc16_CCITT_FALSE);
          ?CrcTest(crc16_X25);
          ?CrcTest(crc16_XMODEM);
          ?CrcTest(crc16_DNP);
          ?CrcTest(crc32);
          ?CrcTest(crc32_MPEG2);

          ?return?0;
          }

          注意

          不同的CRC算法,對00H或FFH數(shù)據(jù)流的計(jì)算結(jié)果不一樣,部分算法存在校驗(yàn)結(jié)果也為00H或FFH的情況(也就意味著存儲(chǔ)空間處于初始化狀態(tài)時(shí):全0或全1,CRC校驗(yàn)反而是正確的),在應(yīng)用中需要注意避免。

          - END -

          瀏覽 81
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产美女日逼视频 | 青青草视频在线免费看 | 日本一级黃色大片看免费 | 首页亚洲中文字幕视频 | 国产一级a毛一级a看免费视频黑人 |