網上大部分的程序都是采用字節方式實現的,在我的程序中用起來不方便,所以打算采用python中的list數據結構自己實現按照比特運算的方式實現一下。
《GB/T 7496-1987》中關於CRC校驗的描述:

AIS采用的CRC-16校驗方法為CRC-16 CCITT(0xFFFF)標准。
MATLAB的實現代碼為:
list_in=[1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0]; L=length(list_in); CRC=[1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,]; poly_list=[0,0,0,1, 0,0,0,0, 0,0,1,0, 0,0,0,1]; for index=1:L CRC=[CRC,0]; if bitxor(list_in(index), CRC(1)) == 1 CRC=CRC(2:17); CRC=bitxor(CRC,poly_list); else CRC=CRC(2:17); end end ~CRC
Python3的實現代碼:
def CRC_Check(list_in):
poly_list=[0,0,0,1, 0,0,0,0, 0,0,1,0, 0,0,0,1]#0x1021,校驗表達式
CRC=[1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1]#初始為0xFFFF
for index in range(len(list_in)):
CRC.append(0)
if list_in[index] ^ CRC[0] == 1:
CRC.pop(0)
for loop in range(len(CRC)):
CRC[loop] = CRC[loop] ^ poly_list[loop]
else:
CRC.pop(0)
return CRC
#list_184為已知測試list,其中前168比特為有效數據,后16比特為CRC校驗
list_184=[1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0,
0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0]
Length=len(list_184)
#list_112為已知測試list,其中前96比特為有效數據,后16比特為CRC校驗
list_112=[1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0,
0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0]
#list_112的正確結果:1010 0001 1011 0100
#my_str='F6 46 82 A2 9B 0C 72 04 7C 01 50 C4'
m1=[1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0,
1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0]#就按照這個順序,不用恢復到正常的字節順序
CRClist=CRC_Check(m1)
print(CRClist)
------------------------------------------
參考文獻:
1、https://dx.eng.uiowa.edu/eedesign/crc.htm
2、在線計算CRC-10 CCITT (0xFFFF)的網站:https://www.lammertbies.nl/comm/info/crc-calculation
