您的位置 首页 解答

CRC位域多表查表办法

CRC算法的实现一般可分运算和查表两种,前者靠对某CRC多项式的移位和异或得到,占用程序空间小但速度慢。后者是将前者的运算结果值排列为一

CRC算法的完成一般可分运算和查表两种,前者靠对某CRC多项式的移位和异或得到,

占用程序空间小但速度慢。后者是将前者的运算成果值排列为一个CRC矩阵表格,占用程
序空间大但速度快。
CRC查表办法经典的有两种,因为表格空间的不同,关于CRC8选用全表查询,CRC16以上
选用小表(一般为256个元素的数组)查询。
CRC查表因为CRCN(N=4,8,12,16,20,24,32,48,64,128,…)的不同占用的表格空间差异
很大。每种CRC的多项式对应一张CRC表,例CRC4左右移位各有16个CRC4表。CRC8左右移位
各有256个CRC8表。1个CRC8表占用256个字节,可组成16*16的数组,而1个CRC16表将占用
65536个字节,组成256*256的数组。
CRC位域多表查表方法与传统的CRC查表办法最大的不同在于多表级联紧缩表格空间。
此办法依据CRC的“性质”: CRC[X]=CRC[行,列]=CRC[行,0]^CRC[0,列]。
以CRC8=X8+X5+X4+1为例,它的多项式的数字表达即权值=0x8C,右移CRC8算法。
已知CRC8[0x9A]=0x6F,咱们能够将0x9A用位域划分为高4位(16行)和低4位(16列),即
CRC8[0x9A]=CRC8[0x90 ^ 0x0A]=CRC8[0x09, 0x0A]
依据:CRC[X]=CRC[行,列]=CRC[行,0]^CRC[0,列]
CRC8[0x90 ^ 0x0A]=CRC8[0x90] ^ CRC8[0x0A]=0x11 ^ 0x7E = 0x6F
或CRC8[0x90, 0x0A]=CRC8[0x90, 0] ^ CRC8[0, 0x0A]=0x11 ^ 0x7E = 0x6F
由此可见,CRC8的表格没必要组成16*16的数组,能够用2*16的队伍数组代替。
CRC8_Col[16]={0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41};
CRC8_Row[16]={0x00,0x9D,0x23,0xBE,0x46,0xDB,0x65,0xF8,0x8C,0x11,0xAF,0x32,0xCA,0x57,0xE9,0x74};
查表CRC8[0x9A]=CRC8_Row[0x09] ^ CRC_Col[0x0A]= 0x11 ^ 0x7E = 0x6F
此办法为CRC位域两表查询办法(占用32个字节),位域表达为:
unsigned char Col:4;//D0~D3
unsigned char Row:4;//D4~D7
CRC位域三表查询办法(占用20个字节),位域表达为:
unsigned char Col:3;//D0~D2
unsigned char Row:3;//D3~D5
unsigned char Block:2;//D6~D7
CRC8_Col[8]={0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83};
CRC8_Row[8]={0x00,0xC2,0x9D,0x5F,0x23,0xE1,0xBE,0x7C};
CRC8_Block[4]={0x00,0x46,0x8C,0xCA};
CRC8[0x9A]=CRC8_Block[0x02] ^ CRC8_Row[0x03] ^ CRC8_Col[0x02] = 0x8C ^ 0x5F ^ 0xBC = 0x6F
或CRC8[0x9A]=CRC8[0x80 ^ 0x18 ^ 0x02]=CRC8[0x80]^CRC8[0x18]^ CRC8[0x02]=0x8C^0x5F^0xBC=0x6F
CRC位域四表查询办法(占用16个字节),位域表达为:
unsigned char Col:2;//D0~D1
unsigned char Row:2;//D2~D3
unsigned char Block:2;//D4~D5
unsigned char Segment:2;//D6~D7
CRC8_Col[4]={0x00,0x5E,0xBC,0xE2};
CRC8_Row[4]={0x00,0x61,0xC2,0xA3};
CRC8_Block[4]={0x00,0x9D,0x23,0xBE};
CRC8_Segment[4]={0x00,0x46,0x8C,0xCA};
CRC8[0x9A]=CRC8_Segment[2]^CRC8_Block[1]^CRC8_Row[2]^CRC8_Col[2]=0x8C^0x9D^0xC2^0xBC=0x6F
此办法为多表查询,即多表成果的屡次异或,当大CRC多表查询时,或许由十多个表组成,为编程便利
一般将表紧缩成等长位域的单表或多维数组,以简化程序。故CRC位域四表可组成矩阵:
unsigned char CRCR8_8C_Array[16]=
{
0x00,0x5E,0xBC,0xE2,0x00,0x61,0xC2,0xA3,0x00,0x9D,0x23,0xBE,0x00,0x46,0x8C,0xCA
};
查表程序为:
unsigned char GetCRCR8_8C(unsigned char crcinit, unsigned char crcval)//CRC8右移权值0x8C(X8+X5+X4+1)
{//(能够不要初值crcinit,多字节CRC8时进口需求对crcval做处理)
unsigned char i, crc=0;
crcval = crcinit ^ crcval;//初值^明文,将CRC编码矩阵转化为CRC编码表
for(i = 0;i < 4;i ++)//4表级联查表4次
{
crc ^= CRCR8_8C_Array[(i << 2) | (crcval & 0x03)];//位域宽2每表4个字节
crcval >>= 2;//预备下一个位域,域宽2,每表4字节
}
return crc;
}
相应的移位算法程序为:
unsigned char GetCRCR8_8C(unsigned char crcinit, unsigned char crcval)//CRC8右移权值0x8C(X8+X5+X4+1)
{//(能够不要初值crcinit,多字节CRC8时进口需求对crcval做处理)
unsigned char i, crc;
crc = crcinit ^ crcval;//初值^明文,将CRC编码矩阵转化为CRC编码表
for(i = 0;i < 8;i ++)//每字节8位
{
if (crc & 0x01)//右移回忆最低位
{
crc >>= 1;
crc ^= 0x8C;//权值
}
else
{
crc >>= 1;
}
}
return crc;
}
下面以CRC16的位域多表查表办法来说明大CRC位域多表查表方法。为一致办法选用等位域4即每表16个元素举例.
左移CRC16=X16+X12+X5+1,多项式即权值=0x1021
CRC16[0x1234]=0x13C6,可分解为
CRC16[0x1234]=CRC16[0x1000 ^ 0x0200 ^ 0x0030 ^ 0x0004]
=CRC16[0x1000] ^ CRC16[0x0200] ^ CRC16[0x0030] ^ CRC16[0x0004]
=0x0373 ^ 0x6662 ^ 0x3653 ^ 0x4084 = 0x13C6
咱们能够构成CRC16表:
CRC16_Array[4, 16]={
{CRC16[0x0000], CRC16[0x0001], CRC16[0x0002],…CRC16[0x000D], CRC16[0x000E], CRC16[0x000F]},
{CRC16[0x0000], CRC16[0x0010], CRC16[0x0020],…CRC16[0x00D0], CRC16[0x00E0], CRC16[0x00F0]},
{CRC16[0x0000], CRC16[0x0100], CRC16[0x0200],…CRC16[0x0D00], CRC16[0x0E00], CRC16[0x0F00]},
{CRC16[0x0000], CRC16[0x1000], CRC16[0x2000],…CRC16[0xD000], CRC16[0xE000], CRC16[0xF000]}
};
unsigned int CRCL16_1021_Array[4, 16]={
{//位域D0~D3
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
},
{//位域D4~D7
0x0000, 0x1231, 0x2462, 0x3653, 0x48C4, 0x5AF5, 0x6CA6, 0x7E97,
0x9188, 0x83B9, 0xB5EA, 0xA7DB, 0xD94C, 0xCB7D, 0xFD2E, 0xEF1F
},
{//位域D8~D11
0x0000, 0x3331, 0x6662, 0x5553, 0xCCC4, 0xFFF5, 0xAAA6, 0x9997,
0x89A9, 0xBA98, 0xEFCB, 0xDCFA, 0x456D, 0x765C, 0x230F, 0x103E
},
{//位域D11~D15
0x0000, 0x0373, 0x06E6, 0x0595, 0x0DCC, 0x0EBF, 0x0B2A, 0x0859,
0x1B98, 0x18EB, 0x1D7E, 0x1E0D, 0x1654, 0x1527, 0x10B2, 0x13C1
}
};
查表程序为(需求4*16*2=128个字节表, 传统查表为256*2=512个字节, 位域法紧缩4倍):
unsigned int GetCRCL16_1021(unsigned int crcinit, unsigned int crcval)//CRC16=X16+X12+X5+1
{//(能够不要初值crcinit,多字节CRC16时进口需求对crcval做处理)
unsigned int i, crc=0;
crcval = crcinit ^ crcval;//初值^明文,将CRC编码矩阵转化为CRC编码表
for(i = 0;i < 4;i ++)//4表级联查表4次(传统查表办法只需2次即2字节)
{
crc ^= CRCL16_1021_Array[i, crcval & 0x0F];//位域宽4每表16个字节
crcval >>= 4;//预备下一个位域,域宽4,每表16字节
}
return crc;
}

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部