当前位置: 首页 > 工具软件 > MinimalModbus > 使用案例 >

利用Python(pyserial、minimalmodbus、modbus_tk)进行单片机通信

裴英才
2023-12-01
  • 背景
    最近利用Python语言设计串口和单片机进行通信的程序,现总结pyserial、 minimalmodbus、modbus_tk各模块使用步骤和注意事项。

  • 系统环境
    Win7、python 3.7

  • 获取串口
    安装依赖包:pip install pyserial
    导包 from serial.tools import list_ports后,获取所有串口 [i.device for i in list(list_ports.comports())]

pyserial

(相较于单播而言更适合广播)

 串口初始化创建对象 ser=serial.Serial("COM1",9600,timeout=0.5)  使用COM1口连接串行口, 创建对象中还可以设置停止位、校验、写入超时等参数,也可以在后续具体使用下更改各参数,例更改读超时时间:ser.timeout = 2。
                                                                                                             
ser.read(20) #是读20个字符。

ser.readline() #是读一行,以/n结束,要是没有/n就一直读,阻塞。

ser.readlines()和ser.xreadlines()#都需要设置超时时间。

ser.isOpen() #看看这个串口是否已经被打开。

ser.close() #在串口打开时关闭串口。

ser.write("0003a0010100020001") #向端口写入16进制数据。

ser.inWaiting()#返回接收缓存中的字节数。

ser.flush()#等待所有数据写出。

ser.flushOutput() #终止当前写操作,并丢弃发送缓存中的数据。

ser.flushInput()#丢弃接收缓存中的所有数据。

exception serial.SerialException(常见串口占用)、exception serial.SerialTimeoutException #异常。

注意事项

在广播场景下读取数据会出现粘包现象,造成接收的数据不正确,需要根据自己的使用场景下对接收的数据进行crc、长度等校验。

minimalmodbus

(适合单播)

 minimalmodbus是集成pyserial并在其基础上发展成的。
 
 ser = minimalmodbus.Instrument("COM1", 1, debug=False)#创建串口COM1设备地址为1的对象,其默认波特率为19200, 如需要更改串口参数用ser.serial.baudrate = 9600等形式。
 
 ser.read_register(registeraddress, functioncode)#读取单个寄存器地址的值
 
 ser.write_register(registeraddress,value, functioncode)#写入单个寄存器地址值
 
 ser.read_registers(registeraddress, number_of_registers, functioncode)#读取多个寄存器值
 
ser.write_registers(registeraddress, values)#写入多个寄存器值
这里面包含了很多方法,这里暂介绍这几种方法,更多方法参考自身使用场景需要各位大佬去探索了。

异常:
serial.serialutil.SerialException#串口问题,
minimalmodbus.NoResponseError#设备超时未回复,
minimalmodbus.InvalidResponseError#接收的数据不合格,
minimalmodbus.SlaveReportedException#设备型号不符合

参数含义:
registeraddress #寄存器地址  
functioncode#功能码  
number_of_registers#读取寄存器的个数
value#单个寄存器写入的值
values#多个寄存器写入的值为一个list  (以上数值全部为10进制)

modbus_tk

modbus_tk分主从站,优点是不仅适用modbus_rtu同样适用modbus_tcp。

modbus_rtu创建对象:
先创建串口对象ser = serial.Serial("COM1",9600,timeout=0.5)

主站串口对象tk_ser = modbus_tk.RtuMaster(ser, interchar_multiplier=1.5, interframe_multiplier=3.5), 打开串口tk_ser.open()
从站创建对象的类似,启动串口tk_ser.start()

#进行读取和设置参数主要方法
tk_ser.execute(slave, function_code, starting_address, quantity_of_x, output_value)
#slave从机地址、function_code功能码、starting_address寄存器地址、quantity_of_x读取的寄存器个数、output_value进行设置时设置的值

异常:
	ModbusFunctionNotSupportedError#功能码不支持
	ModbusInvalidResponseError#数据回复不合法
	ModbusInvalidRequestError#请求数据不合法
	InvalidArgumentError#参数不满足

modbus_tcp创建对象类似:
tk_ser = modbus_tk.TcpMaster(host="127.0.0.1", port=502, timeout_in_sec=5.0)
host和port改为连接设备的ip和port就好,具体使用方法和modbus_rtu相同。
  • 总结
    结合自身使用情况:单播情况下使用优先使用minimalmodbus和modbus_tk,封装处理了大部分的异常,对数据校验的准确性,同时modbus_tk又含有主从机涵盖更多使用场景,而minimalmodbus方便上手。pyserial使用更多情况为广播更好,单播也可以使用,只是对数据需要更多处理。
 类似资料: