首页 > 技术文章 > 【Python】AIS中CRC16校验的方法(CRC-16 CCITT 0xFFFF)

waimen 2020-04-01 11:27 原文

 网上大部分的程序都是采用字节方式实现的,在我的程序中用起来不方便,所以打算采用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

推荐阅读