网上关于CRC的原因解释很多,CRC就是输入数据对多项式的一个除法求余数操作,所以这里根据这个思路,通过python,求解CRC结果。以输入数据为未知数,初始状态也为一个未知数,然后对一个已知的多项式进行除法求余。下面以CRC16为例,具体代码如下【其他CRC可以依次类推】。
# based on CRC16
crc_init=['b15','b14','b13','b12','b11','b10','b9','b8','b7','b6','b5','b4','b3','b2','b1','b0']
data_in=['a7','a6','a5','a4','a3','a2','a1','a0']
length_data_in=len(data_in)
length_crc_init=len(crc_init)
polynominl=0x8408
crc_in=[]
for i in range(8):
crc_in.append(crc_init[i])
for i in range(8):
crc_in.append(data_in[i]+'^'+crc_init[8+i])
print(crc_in)
length_crc_in=len(crc_in)
for i in range(8):
poly_temp=polynominl
poly_temp_list=[]
for j in range(16):
if poly_temp & 0x8000==0x8000:
poly_temp_list.append(crc_in[-1])
else:
poly_temp_list.append('')
poly_temp=poly_temp<<1
print(">>",poly_temp_list)
#imply the >>1 and xor
#>>1
crc_in=crc_in[0:-1]
crc_in=['']+crc_in
#xor
crc_in_temp=[]
for j in range(16):
if crc_in[j]=='':
crc_in_temp.append(poly_temp_list[j])
elif poly_temp_list[j]=='':
crc_in_temp.append(crc_in[j])
else:
crc_in_temp.append(crc_in[j]+'^'+poly_temp_list[j])
crc_in=crc_in_temp
print("<<",crc_in_temp)
<< ['a7^b7^a3^b3', 'a6^b6^a2^b2', 'a5^b5^a1^b1', 'a4^b4^a0^b0', 'a3^b3', 'a2^b2^a7^b7^a3^b3', 'a1^b1^a6^b6^a2^b2', 'a0^b0^a5^b5^a1^b1', 'b15^a4^b4^a0^b0', 'b14^a3^b3', 'b13^a2^b2', 'b12^a1^b1', 'b11^a0^b0^a7^b7^a3^b3', 'b10^a6^b6^a2^b2', 'b9^a5^b5^a1^b1', 'b8^a4^b4^a0^b0']
上面输出的16个bit,每个bit都是和输入数据和CRC初始值相关。所以根据输入数据和初始值,然后按照上面的的公式,就可以直接算出CRC的最终值,而不需要进行多次移位异或操作。在已知CRC结构的前提下,就可以优化软件或者硬件的执行步骤和资源。
根据上面的关系,可以得到软件CRC计算的最终表达式,如下所示:
func CRC16(data []byte) [2]byte {
crc := uint32(0x6363)
for _, bt := range data
{
bt ^= uint8(crc & 0xff)
bt ^= bt << 4
bt32 := uint32(bt)
crc = (crc >> 8) ^ (bt32 << 8) ^ (bt32 << 3) ^ (bt32 >> 4)
}
return [2]byte{byte(crc & 0xff), byte((crc >> 8) & 0xff)}
}