男女午夜激情_www.天堂av.com_亚洲综合小说区_亚洲欧美自拍视频_成年精品_久久www免费人成—看片_激情综合五月天_久久高潮视频_最新国产成人ab网站_国产精品卡一

當前位置:機電之家首頁 >> PLC技術>> PLC基礎 >> PLC通信 >> CRC校驗原理與其C語言實現
CRC校驗原理與其C語言實現

     CRC校驗碼的基本思想是利用線性編碼理論,在發送端根據要傳送的k位二進制碼序列,以一定的規則產生一個校驗用的監督碼(既CRC碼)r位,并附在信息后邊,構成一個新的二進制碼序列數共(k+ r)位,最后發送出去。在接收端,則根據信息碼和CRC碼之間所遵循的規則進行檢驗,以確定傳送中是否出錯。
      在數據存儲和數據通訊領域,CRC無處不在:著名的通訊協議X.25的FCS(幀檢錯序列)采用的是CRC. CCITT,ARJ、LHA等壓縮工具軟件采用的是CRC32,磁盤驅動器的讀寫采用了CRC16,通用的圖像存儲格式GIF、TIFF等也都用CRC作為檢錯手段。
      CRC的本質是模-2除法的余數,采用的除數不同,CRC的類型也就不一樣。通常,CRC的除數用生成多項式來表示。最常用的CRC碼的生成多項式有CRC16,CRC32.
      以CRC16為例,16位的CRC碼產生的規則是先將要發送的二進制序列數左移16位(既乘以2^16)后,再除以一個多項式,最后所得到的余數既是 CRC碼,如下式所示,其中K(X)表示n位的二進制序列數,G(X)為多項式,Q(X)為整數,R(X)是余數(既CRC碼)。
K(X)>>16=G(x)Q(x)+R(x)
      求CRC碼所采用模2加減運算法則,既是不帶進位和借位的按位加減,這種加減運算實際上就是邏輯上的異或運算,加法和減法等價,乘法和除法運算與普通代數式的乘除法運算是一樣,符合同樣的規律。生成CRC碼的多項式如下,其中CRC-16和CRC-CCITT產生16位的CRC碼,而CRC-32則產生的是32位的CRC碼 
      接收方將接收到的二進制序列數(包括信息碼和CRC碼)除以多項式,如果余數為0,則說明傳輸中無錯誤發生,否則說明傳輸有誤,關于其原理這里不再多述。用軟件計算CRC碼時,接收方可以將接收到的信息碼求CRC碼,比較結果和接收到的CRC碼是否相同。
      CCITT推薦的高級數據鏈路控制規程HDLC的幀校驗序列FCS中,使用CCITT-16即CRC16,其生成多項式為G(x)=x16+x12+x5 +1, CRC-32的生成多項式為G(x)=x32+x26+x23+x22+x16+x11+x10+x16+x8+x7+x5+x4+x2+x+1

      以上是摘錄的一段介紹,是不是覺得很玄?我第一次看也是覺得很暈,后來查詢了一些規約和協議的實現資料以后,才恍然大悟。以下是我實現的一段C++代碼,只實現了CRC16,CRC32的實現基本類似,網上有很多資源。其實實現起來非常簡單,就是查表、異或運算而已!查表法實現起來比較簡單,耗資源也比較少,速度較快。只要通信雙方采用的同樣的余數表,就可以正確進行CRC校驗。余數表并沒有硬性規定。許多程序還把余數表做成自動生成,那樣適用性就更好了。

//CRC計算主函數:
//內容:
#include "CrcCode.h"

using namespace std;

unsigned short int CrcCode::CrcCode16(const char *CrcSrcCode,const size_t CodeLength)
{
      unsigned short CRC_Code[]={
              0x0673,0x1652,0x2631,0x3610,0x46F7,0x56D6,0x66B5,0x7694,0x877B,0x975A,//10
              0xA739,0xB718,0xC7FF,0xD7DE,0xE7BD,0xF79C,0x1442,0x0463,0x3400,0x2421,//20
              0x54C6,0x44E7,0x7484,0x64A5,0x954A,0x856B,0xB508,0xA529,0xD5CE,0xC5EF,//30
              0xF58C,0xE5AD,0x2211,0x3230,0x0253,0x1272,0x6295,0x72B4,0x42D7,0x52F6,//40
              0xA319,0xB338,0x835B,0x937A,0xE39D,0xF3BC,0xC3DF,0xD3FE,0x3020,0x2001,//50
              0x1062,0x0043,0x70A4,0x6085,0x50E6,0x40C7,0xB128,0xA109,0x916A,0x814B,//60               0xF1AC,0xE18D,0xD1EE,0xC1CF,0x4EB7,0x5E96,0x6EF5,0x7ED4,0x0E33,0x1E12,//70
              0x2E71,0x3E50,0xCFBF,0xDF9E,0xEFFD,0xFFDC,0x8F3B,0x9F1A,0xAF79,0xBF58,//80
              0x5C86,0x4CA7,0x7CC4,0x6CE5,0x1C02,0x0C23,0x3C40,0x2C61,0xDD8E,0xCDAF,//90
              0xFDCC,0xEDED,0x9D0A,0x8D2B,0xBD48,0xAD69,0x6AD5,0x7AF4,0x4A97,0x5AB6,//100
              0x2A51,0x3A70,0x0A13,0x1A32,0xEBDD,0xFBFC,0xCB9F,0xDBBE,0xAB59,0xBB78,//110
              0x8B1B,0x9B3A,0x78E4,0x68C5,0x58A6,0x4887,0x3860,0x2841,0x1822,0x0803,//120
              0xF9EC,0xE9CD,0xD9AE,0xC98F,0xB968,0xA949,0x992A,0x890B,0x97FB,0x87DA,//130 
              0xB7B9,0xA798,0xD77F,0xC75E,0xF73D,0xE71C,0x16F3,0x06D2,0x36B1,0x2690,//140
              0x5677,0x4656,0x7635,0x6614,0x85CA,0x95EB,0xA588,0xB5A9,0xC54E,0xD56F,//150
              0xE50C,0xF52D,0x04C2,0x14E3,0x2480,0x34A1,0x4446,0x5467,0x6404,0x7425,//160
              0xB399,0xA3B8,0x93DB,0x83FA,0xF31D,0xE33C,0xD35F,0xC37E,0x3291,0x22B0,//170
              0x12D3,0x02F2,0x7215,0x6234,0x5257,0x4276,0xA1A8,0xB189,0x81EA,0x91CB,//180
              0xE12C,0xF10D,0xC16E,0xD14F,0x20A0,0x3081,0x00E2,0x10C3,0x6024,0x7005,//190
              0x4066,0x5047,0xDF3F,0xCF1E,0xFF7D,0xEF5C,0x9FBB,0x8F9A,0xBFF9,0xAFD8,//200 字串3
              0x5E37,0x4E16,0x7E75,0x6E54,0x1EB3,0x0E92,0x3EF1,0x2ED0,0xCD0E,0xDD2F,//210
              0xED4C,0xFD6D,0x8D8A,0x9DAB,0xADC8,0xBDE9,0x4C06,0x5C27,0x6C44,0x7C65,//220
              0x0C82,0x1CA3,0x2CC0,0x3CE1,0xFB5D,0xEB7C,0xDB1F,0xCB3E,0xBBD9,0xABF8,//230
              0x9B9B,0x8BBA,0x7A55,0x6A74,0x5A17,0x4A36,0x3AD1,0x2AF0,0x1A93,0x0AB2,//240
              0xE96C,0xF94D,0xC92E,0xD90F,0xA9E8,0xB9C9,0x89AA,0x998B,0x6864,0x7845,//250
              0x4826,0x5807,0x28E0,0x38C1,0x08A2,0x1883                               //256


      };                                                     //CRC_Code[]數組就是一個余數表
          unsigned short int n_CrcCode16=0;
          unsigned short int bbbbbbbb=0;
          for(size_t i=0;i!=CodeLength;i++)
          {
              bbbbbbbb=(n_CrcCode16 & 0xff)^(CrcSrcCode[i] & 0xff);             //查表,事實上就是獲取該余數在CRC_Code[]數組的中的位置
              n_CrcCode16=((n_CrcCode16>>8) & 0xff) ^ CRC_Code[bbbbbbbb];       //從表中取值計算

          }
          std::cout<<"The CrcCode you need is:"<<n_CrcCode16<<endl;
          return n_CrcCode16;
}

      當然了,你要做的就是給它傳遞參數,也就是你要計算的數據,char類型。一般的串口通信、網絡通信都是字符型通信,更適用于LINUX里面的字符型設備。這個類是在Suse10.1下面用Kdevelop寫的,全部使用ANSI C/C++編寫,在Linux和bbbbbbs均可以編譯通過并且正確運行。
/************************************************************
crc16校驗程序
uint crc16(uint crcdata,uchar bufdata)
形參:bufdata     需要校驗數據
       crcdata     校驗后的數據
功能:接收字節crc校驗,返回校驗值
*************************************************************/
uint crc16(uint crcdata,uchar bufdata)
{
uchar i;

crcdata^=bufdata;
for(i=8;i>0;i--)
{
      crcdata>>=1;
      if(crcdata&0x01)
      crcdata^=0xa001;
     }
return crcdata;
}
VBvbvbvbvbvbvbvvvvvvvvvvvvvvvvvvbbbbbbbbbbbbbbbbbb
Private Sub Command1_Click()
          Dim CRC()       As Byte
          Dim d()       As Byte       '待傳輸數據
          ReDim d(5) As Byte
          d(0) = 2 '02 03 00 00 00 04    lo44 hi3A
          d(1) = 3
          d(2) = 0 字串2
          d(3) = 0
          d(4) = 0
          d(5) = 4 '02 03 20 40 00 04    hi2E Lo4E
     
          CRC = CRC16(d)         '調用CRC16計算函數
          'CRC(0)為高位
          'CRC(1)為低位
        End Sub
        '注意:在數據傳輸時CRC的低位可能在前,而高位在后。
   
        Function CRC16(data() As Byte) As bbbbbb
          Dim CRC16Lo       As Byte, CRC16Hi         As Byte          'CRC寄存器 字串8
          Dim CL       As Byte, CH         As Byte                    '多項式碼&HA001
          Dim SaveHi       As Byte, SaveLo         As Byte
          Dim i       As Integer
          Dim Flag       As Integer
          CRC16Lo = &HFF
          CRC16Hi = &HFF
          CL = &H1
          CH = &HA0
          For i = 0 To UBound(data) 字串6
            CRC16Lo = CRC16Lo Xor data(i)             '每一個數據與CRC寄存器進行異或
            For Flag = 0 To 7
              SaveHi = CRC16Hi
              SaveLo = CRC16Lo
              CRC16Hi = CRC16Hi \ 2                      '高位右移一位
              CRC16Lo = CRC16Lo \ 2                      '低位右移一位
              If ((SaveHi And &H1) = &H1) Then                 '如果高位字節最后一位為1 字串1
                CRC16Lo = CRC16Lo Or &H80                '則低位字節右移后前面補1
              End If                                 '否則自動補0
              If ((SaveLo And &H1) = &H1) Then                 '如果LSB為1,則與多項式碼進行異或
                CRC16Hi = CRC16Hi Xor CH
                CRC16Lo = CRC16Lo Xor CL 
              End If
            Next Flag
          Next i
          Dim ReturnData(1)       As Byte
          ReturnData(0) = CRC16Hi                    'CRC高位
          ReturnData(1) = CRC16Lo                    'CRC低位
          CRC16 = ReturnData
        End Function

 

作者:未知 點擊:1483次 [打印] [關閉] [返回頂部]
本文標簽:CRC校驗原理與其C語言實現
* 由于無法獲得聯系方式等原因,本網使用的文字及圖片的作品報酬未能及時支付,在此深表歉意,請《CRC校驗原理與其C語言實現》相關權利人與機電之家網取得聯系。
電子樣本

SN系列樣冊
:鞏經理
:13915946763
:南京塞姆泵業有限公司
個人求購

王經理 【求購】  西湖輪胎  2026-3-20
蘇紅慶 【求購】  工業除濕機  2026-3-20
金喜 【求購】  線纜  2026-3-20
林杰 【求購】  自粘結鐵芯  2026-3-20
任建波 【求購】  鋰電鉆  2026-3-20
劉經理 【求購】  吊具電纜總...  2026-3-20
潘梟 【求購】  高強鋼焊絲  2026-3-19
李經理 【求購】  丹弗斯液壓...  2026-3-18
VIP公司推薦

主站蜘蛛池模板: 平定县| 修水县| 伽师县| 桦南县| 马尔康县| 台山市| 阿拉善右旗| 宜昌市| 霍邱县| 广灵县| 如皋市| 贵港市| 白沙| 祁东县| 桃园市| 沙洋县| 东辽县| 石台县| 柳林县| 晋宁县| 内黄县| 和硕县| 苏尼特左旗| 措勤县| 梨树县| 武乡县| 海门市| 林甸县| 南阳市| 花垣县| 湄潭县| 通榆县| 绥棱县| 云梦县| 荆州市| 郓城县| 承德市| 茂名市| 葵青区| 侯马市| 垦利县|