在理解了驱动表算法的基础上,下一步就是如何生成这张表,下面我们假设 message = 1011 0100b ,poly = 1 0001 1100b ,驱动表索引为 4bit ,表内存储的数据为 8bit。
最开始索引为 1011b (11),于是我们在驱动表内查找索引为 11 的数据,并将其和 0100 0000b 这之后的 8bit 消息异或,得到结果 1000 0100b,整个流程可以参考下图:
其实这整个运算可以看成消息 1011 0100 0000b 与矩形框内的所有数据异或(注意有补零操作),最终得到结果 1000 0100b。由于异或操作满足 A^B^C = A^(B^C),我们可以先计算整个矩形框内的数据异或结果:1011 1100 0100b,观察可以看出,前 4 bit 就是驱动表索引,后 8 bit 就是驱动表内容,所以说驱动表法的核心是将多次运算存储成一张表,需要时直接查表,成倍地节省时间。
具体代码如下:
#define LUT_WIDTH 4
#define CRC_WIDTH 8
#define CRC_POLY 0x11C
for(index=0; index<(1<<LUT_WIDTH); index++){
temp = 0;
for(bit_cnt=LUT_WIDTH; bit_cnt>0; bit_cnt--){
if((index>>(bit_cnt-1) ^ temp>>(CRC_WIDTH-1))&0x1)
temp = (temp<<1) ^ CRC_POLY;
else
temp <<= 1;
}
table[index] = (unsigned char)temp;
}
for(index=0; index<(1<<LUT_WIDTH); index++) 遍历了所有的索引(0 - 255),for(bit_cnt=LUT_WIDTH; bit_cnt>0; bit_cnt--) 表示处理索引的每一个 bit,从高位开始,$[4, 3, 2, 1]$,if((index>>(bit_cnt-1) ^ temp>>(CRC_WIDTH-1))&0x1) 判断当前索引的当前 bit 是否为 1,若为 1 则与 poly 异或,否则跳过。最后去取 8 位结果存入驱动表。
如果不太能理解,手动模拟一遍就好了。