| 发表于:2007-11-30 23:57:23 楼主 |
网络上找到的,先收藏到这里 vb下如何编写crc校验程序 随着计算机技术的不断发展,在现代工业中,利用微机进行数据通讯的工业控制应用得也越来越广泛。由于传输距离、现场状况等诸多可能出现的因素影响,计算机与受控设备之间的通讯数据常会发生无法预测的错误。为了防止错误所带来的影响,一般在通讯时采取数据校验的办法,而循环冗余码校验是最常用的校验方法之一。 一、 循环冗余码校验原理 循环冗余码校验英文名称为cyclical redundancy check,简称crc。它是利用除法及余数的原理来作错误侦测(error detecting)的。实际应用时,发送装置计算出crc值并随数据一同发送给接收装置,接收装置对收到的数据重新计算crc并与收到的crc相比较,若两个crc值不同,则说明数据通讯出现错误。 根据应用环境与习惯的不同,crc又可分为以下几种标准: ①crc-12码; ②crc-16码; ③crc-ccitt码; ④crc-32码。 crc-12码通常用来传送6-bit字符串。crc-16及crc-ccitt码则用是来传送8-bit字符,其中crc-16为美国采用,而crc-ccitt为欧洲国家所采用。crc-32码大都被采用在一种称为point-to-point的同步传输中。 下面以最常用的crc-16为例来说明其生成过程。 crc-16码由两个字节构成,在开始时crc寄存器的每一位都预置为1,然后把crc寄存器与8-bit的数据进行异或,之后对crc寄存器从高到低进行移位,在最高位(msb)的位置补零,而最低位(lsb,移位后已经被移出crc寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果lsb为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时crc寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后crc寄存器内的值即为最终的crc值。 下面为crc的计算过程: 1.设置crc寄存器,并给其赋值ffff(hex)。 2.将数据的第一个8-bit字符与16位crc寄存器的低8位进行异或,并把结果存入crc寄存器。 3.crc寄存器向右移一位,msb补零,移出并检查lsb。 4.如果lsb为0,重复第三步;若lsb为1,crc寄存器与多项式码相异或。 5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。 6.重复第2至第5步直到所有数据全部处理完成。 7.最终crc寄存器的内容即为crc值。 二、 循环冗余码校验程序的编写 明白了crc校验码的产生过程,编写起程序来就非常容易了。由于visual basic的广泛普及以及其在数据通讯中的重要地位,下面就以vb语言来编写crc的生成程序,其它语言只需稍做修改即可。 编写crc校验程序有两种办法:一种为计算法,一种为查表法。下面对两种方法分别讨论。 1.计算法 计算法就是依据crc校验码的产生原理来设计程序。其优点是模块代码少,修改灵活,可移植性好。其缺点为计算量大。为了便于理解,这里假定了三位数据,而多项式码为a001(hex)。 在窗体上放置一命令按钮command1,并添加如下代码: private sub command1_click() dim crc() as byte dim d() as byte '待传输数据 redim d(2) as byte d(0) = 123 d(1) = 112 d(2) = 135 crc = crc16(d) '调用crc16计算函数 'crc(0)为高位 'crc(1)为低位 end sub 注意:在数据传输时crc的低位可能在前,而高位在后。 function crc16(data() as byte) as string dim crc16lo as byte, crc16hi as byte 'crc寄存器 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) 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 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 2.查表法 查表法的优缺点与计算法的正好相反。为了便于比较,这里所有的假定与计算法的完全相同,都而在窗体上放置一个command1的按钮,其代码部分与上面的也完全一致。下面只介绍crc函数的编写源代码。 private function crc16(data() as byte) as string dim crc16hi as byte dim crc16lo as byte crc16hi = &hff crc16lo = &hff dim i as integer dim iindex as long for i = 0 to ubound(data) iindex = crc16lo xor data(i) crc16lo = crc16hi xor getcrclo(iindex) '低位处理 crc16hi = getcrchi(iindex) '高位处理 next i dim returndata(1) as byte returndata(0) = crc16hi 'crc高位 returndata(1) = crc16lo 'crc低位 crc16 = returndata end function 'crc低位字节值表 function getcrclo(ind as long) as byte getcrclo = choose(ind + 1, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, _ &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40, &h1, &hc0, &h80, &h41, &h1, &hc0, &h80, &h41, &h0, &hc1, &h81, &h40) end function 'crc高位字节值表 function getcrchi(ind as long) as byte getcrchi = choose(ind + 1, &h0, &hc0, &hc1, &h1, &hc3, &h3, &h2, &hc2, &hc6, &h6, &h7, &hc7, &h5, &hc5, &hc4, &h4, &hcc, &hc, &hd, &hcd, &hf, &hcf, &hce, &he, &ha, &hca, &hcb, &hb, &hc9, &h9, &h8, &hc8, &hd8, &h18, &h19, &hd9, &h1b, &hdb, &hda, &h1a, &h1e, &hde, &hdf, &h1f, &hdd, &h1d, &h1c, &hdc, &h14, &hd4, &hd5, &h15, &hd7, &h17, &h16, &hd6, &hd2, &h12, &h13, &hd3, &h11, &hd1, &hd0, &h10, &hf0, &h30, &h31, &hf1, &h33, &hf3, &hf2, &h32, &h36, &hf6, &hf7, &h37, &hf5, &h35, &h34, &hf4, &h3c, &hfc, &hfd, &h3d, &hff, &h3f, &h3e, &hfe, &hfa, &h3a, &h3b, &hfb, &h39, &hf9, &hf8, &h38, &h28, &he8, &he9, &h29, &heb, &h2b, &h2a, &hea, &hee, &h2e, &h2f, &hef, &h2d, &hed, &hec, &h2c, &he4, &h24, &h25, &he5, &h27, &he7, &he6, &h26, &h22, &he2, &he3, &h23, &he1, &h21, &h20, &he0, &ha0, &h60, _ &h61, &ha1, &h63, &ha3, &ha2, &h62, &h66, &ha6, &ha7, &h67, &ha5, &h65, &h64, &ha4, &h6c, &hac, &had, &h6d, &haf, &h6f, &h6e, &hae, &haa, &h6a, &h6b, &hab, &h69, &ha9, &ha8, &h68, &h78, &hb8, &hb9, &h79, &hbb, &h7b, &h7a, &hba, &hbe, &h7e, &h7f, &hbf, &h7d, &hbd, &hbc, &h7c, &hb4, &h74, &h75, &hb5, &h77, &hb7, &hb6, &h76, &h72, &hb2, &hb3, &h73, &hb1, &h71, &h70, &hb0, &h50, &h90, &h91, &h51, &h93, &h53, &h52, &h92, &h96, &h56, &h57, &h97, &h55, &h95, &h94, &h54, &h9c, &h5c, &h5d, &h9d, &h5f, &h9f, &h9e, &h5e, &h5a, &h9a, &h9b, &h5b, &h99, &h59, &h58, &h98, &h88, &h48, &h49, &h89, &h4b, &h8b, &h8a, &h4a, &h4e, &h8e, &h8f, &h4f, &h8d, &h4d, &h4c, &h8c, &h44, &h84, &h85, &h45, &h87, &h47, &h46, &h86, &h82, &h42, &h43, &h83, &h41, &h81, &h80, &h40) end function |
|
|
|
|