代码:
import crcmod
import struct
class Modbus_Crc:
"""
进行modbus crc校验的类:
成员函数:
1、生成函数:传入需要校验的字节流,返回在这个字节流末尾附加了校验码的新字节流
2、校验函数:传入末尾带有校验码的字节流,对这个字节流进行校验,并更加校验是否正确,返回去除了校验码的字节流
"""
def __init__(self):
"""
获取进行modbus crc校验的函数
"""
self.__modbus_func = crcmod.predefined.mkPredefinedCrcFun("modbus")
def __generator_crc(self, bytetream):
"""
对传入的字节流进行modbus crc校验,返回校验码
:param bytetream:需要校验的字节流
:return:modbus crc校验码
"""
if not isinstance(bytetream, bytes):
raise TypeError("bytestream should be an instance of class bytes")
crc = self.__modbus_func(bytetream)
return crc
def __exchange_high_low_byte(self, value):
if not isinstance(value, int):
raise TypeError("value should be a int")
low = value & 0xFF
high = (value >> 8) & 0xFF
return low << 8 | high
def __get_high_low_byte(self, value):
"""
获取传入整数的低8组成的一个字节位和次低8位组成的一个字节
:param value: 整数
:return: high表示次低8位组成的一个字节,high表示次低八位组成的一个字节
"""
if not isinstance(value, int):
raise TypeError("value should be a int")
low = value & 0xFF
high = (value >> 8) & 0xFF
return high, low
def make_byte_stream_with_modbus_crc(self, bytestream):
"""
对传入的字节流modbus crc,产生校验码,校验码低位在前,高位在后的附加到传入字节流末尾并返回带校验的字节流
:param bytestream: 需要产生字节流
:return: 返回带校验的字节流
"""
if not isinstance(bytestream, bytes):
raise TypeError("bytestream should be an instance of class bytes")
crc = self.__generator_crc(bytestream)
high, low = self.__get_high_low_byte(crc)
return bytestream + struct.pack("BB", low, high)
def check_stream_width_modbus_crc(self, bytestream):
"""
对传入带校验的字节流中的数据进行校验与字节流末尾两位校验码进行比较,如果正确,返回True和去除校验部分的数据组成的元组
如果错误,则返回False和None组成的元组
:param bytestream: 末尾带有校验码的字节流
:return: 如果正确,返回True和去除校验部分的数据组成的元组
如果错误,则返回False和None组成的元组
"""
if not isinstance(bytestream, bytes):
raise TypeError("bytestream should be an instance of class bytes")
if len(bytestream) < 3:
raise ValueError("bytestream should be longer than 3")
crc_r = bytestream[-2:]
data = bytestream[:-2]
(low, high) = struct.unpack("BB", crc_r)
crc = self.__generator_crc(data)
if high << 8 | low == crc:
return True, data
else:
return False, None
# 对这个类进行测试:
if __name__ == "__main__":
print("*" * 20)
crc_check = Modbus_Crc()
# 传入的字节流后面附加上校验码
stream = crc_check.make_byte_stream_with_modbus_crc(b'\x61\x62\x63\x64\xFF\xFE')
print(stream)
# 对传入的数据进行校验,返回校验结果,和字节流数据部分
ret, data = crc_check.check_stream_width_modbus_crc(stream)
print(ret, data)
测试:
![](https://img-blog.csdnimg.cn/4e6ae8cfb3b2499f886105b95d33cb34.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAeXV5dXl1bGlhbmcwMA==,size_20,color_FFFFFF,t_70,g_se,x_16)