您的位置 首页 厂商

CRC校验—之avrbootloader

先看一下要用到的函数。#includeutil/crc16.h>这是计算单个字节的CRC(旧crc与data生成)static__inline__uint16_t_crc_xmodem_up..

先看一下要用到的函数。

#include

这是核算单个字节的CRC(旧crc与data生成)

static __inline__ uint16_t _crc_xmodem_update(uint16_t __crc, uint8_t __data);
多项式Polynomial: x^16 + x^12 + x^5 + 1 (0x1021)
crc初始值Initial value: 0x0
专用于XMODEM通讯协议,等效于C写的
uint16_t crc_xmodem_update (uint16_t crc, uint8_t data)
{
int i;
crc = crc ^ ((uint16_t)data << 8);
for (i=0; i<8; i++)
{
if (crc & 0x8000)

crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}

下面是核算count个数据(*ptr)的CRC。

先核算第一个字节数据的CRC,然后核算下一个字节数据的CRC。顺次核算其他数据的CRC。一切的字符处理完结后CRC寄存器内的值即为终究的CRC值。

//核算CRC16
unsigned int calcrc(unsigned char *ptr, unsigned char count)
{
unsigned int crc = 0;
while (count–)
{
crc =_crc_xmodem_update(crc,*ptr++);
}
return crc;
}

在主函数里是这样调用的

crc=strXMODEM.CRC16hi<<8;
crc+=strXMODEM.CRC16lo;

crc为主机发送过来的校验码

//AVR的16位整数是低位在先,XMODEM的CRC16是高位在先
if(calcrc(&strXMODEM.Xdata[0],128)!=crc) //核算收到的数据的CRC,并判别是否与主机发送过来的CRC

//持平,若不持平,数据犯错,要求重发当时数据块

{
put_c(XMODEM_NAK); //CRC过错,要求重发当时数据块

continue;
}

==================================================

下面为CRC的核算进程:
1.设置CRC寄存器,并给其赋值0000(hex)。
2.将数据的第一个8-bit字符与16位CRC寄存器的高8位进行异或,并把成果存入CRC寄存器。
3.CRC寄存器向左移一位,LSB补零,移出并查看MSB。
4.假如MSB为0,重复第三步;若MSB为1,CRC寄存器与多项式码相异或。
5.重复第3与第4步直到8次移位悉数完结。此刻一个8-bit数据处理完毕。
6.重复第2至第5步直到一切数据悉数处理完结。
7.终究CRC寄存器的内容即为CRC值。

CRC校验选用多项式编码办法。
被处理的数据块能够看作是一个二进制多项式,例如,10110101能够看作是2^7+2^5+2^4+2^2+2^0,多项式乘除法运算进程与一般代数多项式的乘除法相同。多项式的加减法运算以2为模,加减时不进,错位,和逻辑异或运算共同。
选用CRC校验时,发送方和接收方用同一个生成多项式g(x),而且g(x)的首位和终究一位的系数有必要为1。CRC的处理办法是:发送方以g(x)去除t(x),得到余数作为CRC校验码。校验时,以核算的校对成果是否为0为据,判别数据帧是否犯错。

CRC 校验码的算法剖析
CRC 校验码的编码办法是用待发送的二进制数据t(x)除以生成多项式g(x),将终究的余数
作为CRC 校验码。其完成进程如下:
(1) 设待发送的数据块是m 位的二进制多项式t(x),生成多项式为r 阶的g(x)。在数据块
的结尾增加r个0,数据块的长度增加到m+r位,对应的二进制多项式为xr t(x)。
(2) 用生成多项式g(x)去除xr t(x),求得余数为阶数为r-1 的二进制多项式y(x)。此二进
制多项式y(x)便是t(x)经过生成多项式g(x)编码的CRC 校验码。
(3) 用xr t(x)以模2 的办法减去y(x),得到二进制多项式xr t(x)。xr t(x)便是包含了CRC
校验码的待发送字符串。
从 CRC 的编码规矩能够看出,CRC 编码实际上是将代发送的m 位二进制多项式t(x)转换成
了能够被g(x)除尽的m+r位二进制多项式xr t(x),所以解码时能够用接受到的数据去除g(x),
假如余数位零,则表明传输进程没有过错;假如余数不为零,则在传输进程中必定存在过错。许多
CRC 的硬件解码电路便是按这种办法进行检错的。一起xr t(x)能够看做是由t(x)和CRC校验码
的组合,所以解码时将接收到的二进制数据去掉尾部的r 位数据,得到的便是原始数据。
为了更清楚的了解 CRC 校验码的编码进程,下面用一个简略的比如来阐明CRC 校验码的编码
进程。因为CRC-32、CRC-16、CCITT 和CRC-4 的编码进程根本共同,只要位数和生成多项式不
相同。为了叙说简略,用一个CRC-4 编码的比如来阐明CRC 的编码进程。
设待发送的数据 t(x)为12 位的二进制数据100100011100;CRC-4 的生成多项式为g(x)
= x4 + x +1,阶数r为4,即10011。首先在t(x)的结尾增加4 个0 构成x4t(x),数据块就成了
1001000111000000。然后用g(x)去除x4t(x),不必管商是多少,只需要求得余数y(x)。下表为
给出了除法进程。

从上面表中能够看出,CRC 编码实际上是一个循环移位的模2 运算。对

CRC-4,咱们假设有一个5 bits 的寄存器,经过重复的移位和进行CRC 的除

法,那么终究该寄存器中的值去掉最高一位
便是咱们所要求的余数。所以能够将上述进程用下面的流程描绘:
//reg 是一个5 bits 的寄存器
把 reg 中的值置0.
把原始的数据后增加r 个0.
While (数据未处理完)
Begin
If (reg 首位是1)
reg = reg XOR 0011.
把reg 中的值左移一位,读入一个新的数据并置于register 的0 bit 的方位。
End
reg 的后四位便是咱们所要求的余数。
这种算法简略,简单完成,对恣意长度生成多项式的G(x)都适用。在发

送的数据不长的情
况下能够运用。可是假如发送的数据块很长的话,这种办法就不太适宜了。

它一次只能处理一位数
据,功率太低。为了进步处理功率,能够一次处理4 位、8 位、16 位、32

位。因为处理器的结构基
本上都支撑8 位数据的处理,所以一次处理8 位比较适宜。
为了对优化后的算法有一种直观的了解,先将上面的算法换个视点了解一下

。在上面比如中,
能够将编码进程看作如下进程:
因为终究只需要余数,所以咱们只看后四位。结构一个四位的寄存器reg,

初值为0,数据依
次移入reg0(reg 的0 位),一起reg3 的数据移出reg。有上面的算法能够

知道,只要当移出的数据
为1 时,reg 才和g(x)进行XOR 运算;移出的数据为0 时,reg 不与g(x

)进行XOR 运算,相
当与和0000 进行XOR 运算。便是说,reg 和什么样的数据进行XOR 移出的

数据决议。因为只要一
个bit,所以有21种挑选。上述算法能够描绘如下,
//reg 是一个4 bits 的寄存器
初始化 t[]={0011,0000}
把reg 中的值置0.
把原始的数据后增加r 个0.
While (数据未处理完)
Begin
把reg 中的值左移一位,读入一个新的数据并置于register 的0 bit 的方位。
reg = reg XOR t[移出的位]
End
上面算法是以bit 为单位进行处理的,能够将上述算法扩展到8 位,即以

Byte 为单位进行处理,
即CRC-32。结构一个四个Byte 的寄存器reg,初值为0x00000000,数据依

次移入reg0(reg 的0
字节,以下相似),一起reg3 的数据移出reg。用上面的算法类推可知,移

出的数据字节决议reg 和
什么样的数据进行XOR。因为有8 个bit,所以有28种挑选。上述算法能够描

述如下:
//reg 是一个4 Byte 的寄存器
初始化 t[]={…}//共有28=256 项
把 reg 中的值置0.
把原始的数据后增加r/8 个0 字节.
While (数据未处理完)
Begin
把reg 中的值左移一个字节,读入一个新的字节并置于reg 的第0 个byte 的

方位。
reg = reg XOR t[移出的字节]
End

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/272947.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部