好文档 - 专业文书写作范文服务资料分享网站

crc校验原理

天下 分享 时间: 加入收藏 我要投稿 点赞

; Function: CRC one byte ; Input: CRCByte

; Output: CRC_High CRC_Low

;<>-------------------------------------------------------------

CRC_Byte:

clrf CRC_Low clrf CRC_High movlw 09H movwf v_Loop1 movf CRCByte, w movwf CRC_High CRC:

decfsz v_Loop1 ;8次循环,每一位相应计算 goto CRC10 goto CRCend CRC10

bcf STATUS, C rlf CRC_Low rlf CRC_High

btfss STATUS, C

goto CRC ;为0不需计算

movlw 10H ;若多项式改变,这里作相应变化

xorwf CRC_High, f

movlw 21H ;若多项式改变,这里作相应变化

xorwf CRC_Low, f goto CRC CRCend: nop nop return

;<>-------------------------------------------------------------

; CRC one byte end

;<>------------------------------------------------------------- ;<>------------------------------------------------------------- ; Function: CRC date

; Input: BufStart(A,B,C)(一帧数据的起始地址) v_Count (要做CRC的字节数)

; Output: CRC16_High CRC16_Low(结果)

;<>------------------------------------------------------------- CRC_Data:

clrf CRC16_High clrf CRC16_Low

CRC_Data10

movf INDF, w xorwf CRC16_High,w

movwf CRCByte call CRC_Byte incf FSR

decf v_Count ;需计算的字节数

movf CRC_High, w xorwf CRC16_Low, w movwf CRC16_High

movf CRC_Low, w movwf CRC16_Low

movf v_Count, w ;计算结束?

btfss STATUS, Z goto CRC_Data10

return

;<>------------------------------------------------------------- ; CRC date end

;<>-------------------------------------------------------------

说明: CRC 的计算原理如下(一个字节的简单例子)

11011000 00000000 00000000 <- 一个字节数据, 左移 16b ^10001000 00010000 1 <- CRC-CCITT 多项式, 17b --------------------------

1010000 00010000 10 <- 中间余数 ^1000100 00001000 01 ------------------------- 10100 00011000 1100 ^10001 00000010 0001 ----------------------- 101 00011010 110100 ^100 01000000 100001 --------------------- 1 01011010 01010100 ^1 00010000 00100001 -------------------

01001010 01110101 <- 16b CRC

仿此,可推出两个字节数据计算如下:d 为数据,p 为项式,a 为余数 dddddddd dddddddd 00000000 00000000 <- 数据 D ( D1, D0, 0, 0 ) ^pppppppp pppppppp p <- 多项式 P ----------------------------------- ...

aaaaaaaa aaaaaaaa 0 <- 第一次的余数 A’ ( A’1, A’0 )

^pppppppp pppppppp p -------------------------- ...

aaaaaaaa aaaaaaaa <- 结果 A ( A1, A0 )

由此与一字节的情况比较,将两个字节分开计算如下:

先算高字节:

dddddddd 00000000 00000000 00000000 <- D1, 0, 0, 0 ^pppppppp pppppppp p <- P ----------------------------------- ...

aaaaaaaa aaaaaaaa <- 高字节部分余数 PHA1, PHA0

此处的部分余数与前面两字节算法中的第一次余数有如下关系,即 A’1 = PHA1 ^ D0, A’0 = PHA0:

aaaaaaaa aaaaaaaa <- PHA1, PHA0 ^dddddddd <- D0 -----------------

aaaaaaaa aaaaaaaa <- A’1, A’0

低字节的计算:

aaaaaaaa 00000000 00000000 <- A’1, 0, 0 ^pppppppp pppppppp p <- P -------------------------- ...

aaaaaaaa aaaaaaaa <- 低字节部分余数 PLA1, PLA0 ^aaaaaaaa <- A’0 , 即 PHA0 -----------------

aaaaaaaa aaaaaaaa <- 最后的 CRC ( A1, A0 )

总结以上内容可得规律如下: 设部分余数函数 PA = f( d )

其中 d 为一个字节的数据(注意,除非 n = 0 ,否则就不是原始数据,见下文) 第 n 次的部分余数

PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( d ) 其中的

d = ( PA( n - 1 ) >> 8 ) ^ D( n ) 其中的 D( n ) 才是一个字节的原始数据。

公式如下:

PA( n ) = ( PA( n - 1 ) << 8 ) ^ f( ( PA( n - 1 ) >> 8 ) ^ D( n ) )

可以注意到函数 f( d ) 的参数 d 为一个字节,对一个确定的多项

式 P, f( d ) 的返回值 是与 d 一一对应的,总数为 256 项,将这些数据预先算出保存在表里,f( d )就转换为一 个查表的过程,速度也就可以大幅提高,这也就是查表法计算 CRC 的原理。

再来看 CRC 表是如何计算出来的,即函数 f( d ) 的实现方法。分析前面一个字节数据的 计算过程可发现,d 对结果的影响只表现为对 P 的移位异或,看计算过程中的三个 8 位 的列中只低两个字节的最后结果是余数,而数据所在的高 8 位列最后都被消去了,因其 中的运算均为异或,不产生进位或借位,故每一位数据只影响本列的结果,即 d 并不直接 影响结果。再将前例变化一下重列如下: 11011000

-------------------------- 10001000 00010000 1 // P ^ 1000100 00001000 01 // P ^ 000000 00000000 000 // 0 ^ 10001 00000010 0001 // P ^ 0000 00000000 00000 // 0 ^ 100 01000000 100001 // P ^ 00 00000000 0000000 // 0 ^ 1 00010000 00100001 // P ------------------- 01001010 01110101

现在的问题就是如何根据 d 来对 P 移位异或了,从上面的例子看,也可以理解为每步 移位,但根据 d 决定中间余数是否与 P 异或。从前面原来的例子可以看出,决定的条件是中间余数的最高位为0,因为 P 的最高位一定为1,即当中间余数与 d 相应位异或的最高位为1时,中间余数移位就要和 P 异或,否则只需移位即可。其方法如下例(上例的变形,注意其中空格的移动表现了 d 的影响如何被排除在结果之外):

d --------a--------

1 00000000 00000000 <- HSB = 1 0000000 000000000 <- a <<= 1 0001000 000100001 <-不含最高位的 1 -----------------

crc校验原理

;Function:CRConebyte;Input:CRCByte;Output:CRC_HighCRC_Low;-------------------------------------------------------------<
推荐度:
点击下载文档文档为doc格式
28irf50yqg862m61dlcl
领取福利

微信扫码领取福利

微信扫码分享