本帖最后由 dianzi_fans 于 2011-12-3 12:03 编辑
原理 1. 通信双方约定同一个生成多项式 例如 16位的CRC码得生成多项式G(X)=X16+X15+X2+1 即CRC-16的生成多项式系数G=1100 0000 0000 0010 12.发送端假设待发送段的信息为M,M被G除得商为Q 余数为R,那么R即为CRC码 3.发送端发出的数据即为M+R 发送给接收端 4.接收端用同一个生成多项式系数去除M+R 若所得余数为0 则说明接收的信息是无误的,这样就完成了一个数据的发送。
原理的简单证明 以K个信息位为系数构成的多项式称为信息多项式K(X) 其最高次幂为K-1次 以r个冗余比特为系数构成的多项式称为冗余多项式R(X) 其最高次幂为r-1次 对K(X)左移r位-变为 ,令 所以=C(X) *G(X)+R(X) 两边加上R(X)得+R(X)=C(X) *G(X)+R(X)+R(X)化简得+R(X)=C(X) *G(x)所以+R(X)能被G(X)整除,因此可以规定发送端发出的码为+R(X),假设接收端接收的码为P(X)+E(X)其中E(X)为错误样本,当E(X)=0时 接收端P(X)能被G(X)除尽,则接收的码是正确的。
怎样求CRC码 假设数据传输过程中需要发送15位的二进制信息g=101001110100001,这串二进制码可表示为代数多项式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5 + 1,其中g中第k位的值,对应g(x)中x^k的系数。将g(x)乘以x^m,既将g后加m个0,然后除以m阶多项式h(x),得到的(m-1)阶余项r(x)对应的二进制码r就是CRC编码。 g(x)和h(x)的除运算,可以通过g和h做xor(异或)运算。比如将11001与10101做xor运算 明白了xor运算法则后,举一个例子使用CRC-8算法求101001110100001的效验码。CRC-8标准的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1,既h是9位的二进制串111010101。 经过迭代运算后,最终得到的r是10001100,这就是CRC效验码
VB实现CRC—16码的计算 核心计算程序如下 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'用来计算CRC值的子程序
'BCRC是所要计算的进制值(16或32),如16位CRC时,其值即为16
'GP是生成多项式,以16进制表示较佳,GP=0x11021=10001000000100001
'BDF是欲求出CRC的原始数值
'返回值即是计算后的CRC值
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function CalCRC(BCRC As Integer, GP As Long, BDF As Long) As Long
Dim C1&, C2&
Dim A1%, PreC1&
Dim LeftValue%, A1Shift%
If BDF = 0 Then
CalCRC = 0
Exit Function
End If
A1 = (Len(Hex(BDF)) - 1) * 4 '求出第一次的参考偏移位元值
C1 = BDF * 2 ^ BCRC '将被求值先乘上位值
LeftValue = Val("&H" & Mid(Hex(BDF), 1, 1)) '取出最左边的值
If LeftValue >= 1 Then A1Shift = 1 '只有一位数,权值为1
If LeftValue >= 2 Then A1Shift = 2 '只有二位数,权值为2
If LeftValue >= 4 Then A1Shift = 3 '只有三位数,权值为3
If LeftValue >= 8 Then A1Shift = 4 '四位数,权值为4
A1 = A1 + (A1Shift - 1) '第一次的偏移值
C2 = GP * 2 ^ A1 '第一次的运算值
Do
PreC1 = C1 '记录先前值
C1 = C1 Xor C2 '二进制长除法之余数
Do
A1 = A1 - 1 '''
If C1 > PreC1 Then '若余数大于生成多项式,则予以降序
C1 = PreC1 Xor (GP * 2 ^ A1)
Else
Exit Do
End If
Loop
C2 = GP * 2 ^ A1 '下一次的运算值
Loop Until C1 <= GP '直到余数小于生成多项式
CalCRC = C1
End Function
计算过程演示如下 A1=7
C2=100010000001000010000000
PREC1=110101010000000000000000
C1= C1 XOR C2
C1= 110101010000000000000000 XOR 100010000001000010000000 = 010111010001000010000000 A1=A1-1=7-1=6
C2=10001000000100001000000 ---------------------------------------------------------------------
--------------------------------------------------------------------- PREC1=010111010001000010000000
C1= C1 XOR C2
C1= 010111010001000010000000 XOR 010001000000100001000000 =000110010001100011000000
A1=A1-1=6-1=5
C2=1000100000010000100000 ---------------------------------------------------------------------
--------------------------------------------------------------------- PREC1=000110010001100011000000
C1= C1 XOR C2
C1= 000110010001100011000000 XOR 001000100000010000100000 = 001110110001110011100000
A1=A1-1=5-1=4
此时C1 > PREC1
执行C1 = PreC1 Xor (GP * 2 ^ A1)
C1 =000110010001100011000000 XOR 000100010000001000010000 = 000010000001101011010000 接着返回执行A1=A1-1=4-1=3
但是此时C1 < PREC1
不执行C1 = PreC1 Xor (GP * 2 ^ A1)于是跳出内循环,执行外循环的代码
C2 = GP * 2 ^ A1=10001000000100001000
PREC1=000010000001101011010000
C1= C1 XOR C2
C1= 000010000001101011010000 XOR 000010001000000100001000 =000000001001101111011000
到这里发现C1 < GP
跳出外循环,代码结束最后CalCRC = C1 = 000000001001101111011000 = 1001101111011000 = 9BD8
大部分是网上的资料,计算过程演示是自己推算的。。。。
---------END
|