背景
最近利用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())]
(相较于单播而言更适合广播)
串口初始化创建对象 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是集成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_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相同。