Overview
We did a project some time ago. Our system uses the serial port to interact with the MCU. The system side code has written the code for parsing and sending data according to the data packet protocol agreed by both parties, but the MCU side has not completed the code, we can’t wait for them After the completion of the code debugging, this will delay the progress of the project, after consulting the relevant information online. Finally, I decided to use a python script to complete the analysis and packaging of the data for simulation testing. I also checked a lot of information on the Internet, and finally realized the simulation data to complete the code debugging. This script mainly uses the two modules of python serial (serial port operation) And struct (packed into c language byte string). Some brief instructions:
serial module
The main user serial port operation, there are a lot of information on the network, here is the code directly for comments
class ComThread:
def __init__(self, Port='COM56'): #打开COM56
self.l_serial = None
self.alive = False
self.waitEnd = None
self.port = Port
self.ID = None
self.data = None
def waiting(self):
if not self.waitEnd is None:
self.waitEnd.wait()
def SetStopEvent(self):
if not self.waitEnd is None:
self.waitEnd.set()
self.alive = False
self.stop()
def start(self):
self.l_serial = serial.Serial()
self.l_serial.port = self.port
self.l_serial.baudrate = 115200 #串口波特率
self.l_serial.timeout = 2 #超时时间
self.l_serial.open()
if self.l_serial.isOpen():
self.waitEnd = threading.Event()
self.alive = True
self.thread_read = None
self.thread_read = threading.Thread(target=self.FirstReader)
self.thread_read.setDaemon(1)
self.thread_read.start()
return True
else:
return False
def SendDate(self,i_msg,send):
#lmsg = ''
isOK = False
#发送数据到相应的处理组件
print(i_msg)
send_buf = nwy_create_send_msg(i_msg, send)
self.l_serial.write(send_buf)
print("send success")
return True
def FirstReader(self):
while self.alive:
time.sleep(0.1)
data = ''
data = data.encode('utf-8')
n = self.l_serial.inWaiting()
if n:
data = data + self.l_serial.read(n)
print(len(data))#打印收到的数据
print(data.hex()) #按照十六进制打印
def stop(self):
self.alive = False
self.thread_read.join()
if self.l_serial.isOpen():
self.l_serial.close()
def quit(signum, frame):
print("Bye Bye!")
sys.exit(0)
#调用串口,测试串口
def main():
rt = ComThread()
rt.sendport = '**1*80*'
try:
if rt.start():
signal.signal(signal.SIGINT, quit)
print(rt.l_serial.name)
#rt.waiting()
#print("The data is:%s,The Id is:%s"%(rt.data,rt.ID))
#t.stop()
else:
pass
except Exception as se:
print(str(se))
print ('End OK .')
return rt
if __name__ == '__main__':
mSerial = main()
while True:
time.sleep(1)
struct module
Serial data analysis, here does not use unpack for analysis, here is the analysis according to the current definition
def parse_read_data(data, len):
print(data)
print(len)
#check head
if 0x0F != data[0]:#判断数据头
print ("head is not 0x0F data head is " + hex(data[0]))
return False
#get msg id
msg_id = data[1] << 8 | data[2] #获取消息ID
msg_len = data[3] << 8 | data[4] #获取数据长度
data_crc = data[7+msg_len] #获取数据的校验和
Cal_crc = Calculation_crc(data[1:len-2]) #计算数据的校验和
if data_crc != Cal_crc: #判断数据的校验和
print ("crc error ")
return False
print ("data is good")
#do something
#处理数据
return True
Pack the data to be sent into a fixed format byte string. The specific packing should be packed according to the actual protocol. The detailed explanation of strcut is too much, so I won’t repeat it here.
def create_send_msg(i_msg, send):
msg_len = len(send)
msg_len_2 = ~msg_len
#下面就类似于c预言的printf 不过可以查查struct中对应的类型
# !表示大端
# H unsigned short
# h singned short 这里用h主要是长度的反码如果有无符号会提示存不下,所以用有符号
# %ds 这个比较特殊,s为字节串,长度为%d
# B byte
psh = struct.pack('!HHh%ds'%len(send), i_msg, msg_len, msg_len_2,send)
# 计算crc
crc = Calculation_crc(psh)
# c语言的结构体定义如下
# struct{
# unsigned char header
# unsigned short msgid
# unsigned short msglen
# signed short unmsglen
# char *data
# unsigned char crc
# unsigned char end
# }
pshhh = struct.pack('!BHHh%dsBB' %len(send), MSG_HEADER, i_msg, msg_len, msg_len_2,send, crc, MSG_END)
return pshhh
The complete sample code is as follows
import struct
import binascii
import sys
import signal
import threading
import time
import serial
import random
MSG_HEADER=0x0F
MSG_END=0xF0
MCU_MSG_ID=0x0001
def create_send_msg(i_msg, send):
msg_len = len(send)
msg_len_2 = ~msg_len
#下面就类似于c预言的printf 不过可以查查struct中对应的类型
# !表示大端
# H unsigned short
# h singned short 这里用h主要是长度的反码如果有无符号会提示存不下,所以用有符号
# %ds 这个比较特殊,s为字节串,长度为%d
# B byte
psh = struct.pack('!HHh%ds'%len(send), i_msg, msg_len, msg_len_2,send)
# 计算crc
crc = Calculation_crc(psh)
# c语言的结构体定义如下
# struct{
# unsigned char header
# unsigned short msgid
# unsigned short msglen
# signed short unmsglen
# char *data
# unsigned char crc
# unsigned char end
# }
pshhh = struct.pack('!BHHh%dsBB' %len(send), MSG_HEADER, i_msg, msg_len, msg_len_2,send, crc, MSG_END)
return pshhh
def send_mcu_data(data):
msg = "FF000000FFECFFD7FC03000000000000"; #模拟的一包数据
by = binascii.a2b_hex(msg)
mSerial.SendDate(MCU_MSG_ID, by)
return
#计算校验和
def Calculation_crc(data):
crc = 0
for i in range(len(data)):
crc ^= data[i]
return crc
def parse_read_data(data, len):
print(data)
print(len)
#check head
if 0x0F != data[0]:#判断数据头
print ("head is not 0x0F data head is " + hex(data[0]))
return False
#get msg id
msg_id = data[1] << 8 | data[2] #获取消息ID
msg_len = data[3] << 8 | data[4] #获取数据长度
data_crc = data[7+msg_len] #获取数据的校验和
Cal_crc = Calculation_crc(data[1:len-2]) #计算数据的校验和
if data_crc != Cal_crc: #判断数据的校验和
print ("crc error ")
return False
print ("data is good")
#do something
#处理数据
return True
class ComThread:
def __init__(self, Port='COM56'):
self.l_serial = None
self.alive = False
self.waitEnd = None
self.port = Port
self.ID = None
self.data = None
def waiting(self):
if not self.waitEnd is None:
self.waitEnd.wait()
def SetStopEvent(self):
if not self.waitEnd is None:
self.waitEnd.set()
self.alive = False
self.stop()
def start(self):
self.l_serial = serial.Serial()
self.l_serial.port = self.port
self.l_serial.baudrate = 230400
self.l_serial.timeout = 2
self.l_serial.open()
if self.l_serial.isOpen():
self.waitEnd = threading.Event()
self.alive = True
self.thread_read = None
self.thread_read = threading.Thread(target=self.FirstReader)
self.thread_read.setDaemon(1)
self.thread_read.start()
return True
else:
return False
def SendDate(self,i_msg,send):
send_buf = create_send_msg(i_msg, send)
self.l_serial.write(send_buf)
print("send success")
return True
def FirstReader(self):
while self.alive:
time.sleep(0.1)
data = ''
data = data.encode('utf-8')
n = self.l_serial.inWaiting()
if n:
data = data + self.l_serial.read(n)
#print(len(data))
#print(data.hex())
parse_read_data(data, len(data))
def stop(self):
self.alive = False
self.thread_read.join()
if self.l_serial.isOpen():
self.l_serial.close()
def quit(signum, frame):
print("Bye Bye!")
sys.exit(0)
#调用串口,测试串口
def main():
rt = ComThread()
rt.sendport = '**1*80*'
try:
if rt.start():
signal.signal(signal.SIGINT, quit)
print(rt.l_serial.name)
else:
pass
except Exception as se:
print(str(se))
print ('End OK .')
return rt
if __name__ == '__main__':
mSerial = main()
while True:
time.sleep(1)
#发送给系统数据
send_mcu_data(mSerial)
The above is my sharing, if you need to explore, you can add qq 991410485