寄存器协议地址指指通信时使用的寄存器地址,例如PLC地址40001对应寻址地址0x0000,40002对应寻址地址0x0001,寄存器寻址地址一般使用16进制描述。再如,PLC寄存器地址40003对应协议地址0002,PLC寄存器地址30003对应协议地址0002,虽然两个PLC寄存器寄存器通信时使用相同的地址,但是需要使用不同的命令访问,所以访问时不存在冲突。
参考资料:[](https://blog.csdn.net/xukai871105/article/details/16368615
import serial
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
import struct
import json
#找本机的端口号是多少
PORT = 'COM6'
def WriteFloat(value,reverse=False):
#!:network (= big-endian),f:浮点数,此方法把浮点数转换为字节流
y_bytes = struct.pack('!f',value)
#字节流转化位16进制
y_hex = y_bytes.hex()
n,m = y_hex[:-4],y_hex[-4:]
n,m = int(n,16),int(m,16)
if reverse:
v = [n,m]
else:
v = [m,n]
return v
def ReadFloat(*args,reverse=False):
#十进制转化为16进制,并化为字符串
for n,m in args:
n,m = '{:04x}'.format(n),'{:04x}'.format(m)
if reverse:
v = n + m
else:
v = m + n
#16进制转化为字节流
y_bytes = bytes.fromhex(v)
#转化为浮点数,结果返回的是元组
y = struct.unpack('!f',y_bytes)[0]
#取1位小数点
y = round(y,1)
return y
def ReadDint(*args,reverse=False):
for n,m in args:
n,m = '{:04x}'.format(n),'{:04x}'.format(m)
if reverse:
v = n + m
else:
v = m + n
y_bytes = bytes.fromhex(v)
y = struct.unpack('!i',y_bytes)[0]
return y
def WriteDint(value,reverse=False):
y_bytes = struct.pack('!i',value)
y_hex = y_bytes.hex()
n,m = y_hex[:-4],y_hex[-4:]
n,m = int(n,16),int(m,16)
if reverse:
v = [n,m]
else:
v = [m,n]
return v
def Readint(*args):
n = '{:04x}'.format(args[0][0])
y_bytes = bytes.fromhex(n)
y = struct.unpack('!h',y_bytes)[0]
return y
def Writeint(value):
y_bytes = struct.pack('!h',value)
y_hex = y_bytes.hex()
n= int(y_hex,16)
return n
if __name__ == "__main__":
logger = modbus_tk.utils.create_logger("console")
master = modbus_rtu.RtuMaster(
serial.Serial(port=PORT, baudrate=9600, bytesize=8, parity='N', stopbits=1)
)
master.set_timeout(5.0)
logger.info("connected")
logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 22,
output_value= WriteFloat(123.2)))
tuple = master.execute(1, cst.READ_HOLDING_REGISTERS, 22, 2
print(ReadFloat(tuple)
1、PLC与树莓派基于Modbus_tk库、serial库进行串口通信。通过serial.Serial连接,端口需查看当前连接的端口号,波特率9600,数据位为8位,奇偶校验设置为无,停止位设置为1位。
2、数据均为PLC从各类传感器中获取的数据,使用master.execute传输数据,获取的是十进制,从站为1,cst. WRITE_SINGLE_REGISTER为写入一个保持寄存器、cst. WRITE_MULTIPLE_REGISTERS为写入多个连续保持寄存器、cst. READ_HOLDING_REGISTERS为读取一个或者多个连续保持寄存器、cst. READ_COILS为读取线圈(开关)、cst. WRITE_SINGLE_COIL为写入一个线圈(开关),output_value为输入的十进制,starting_address为寄存器或者线圈的起始地址,quantity_of_x为获取的个数。
3、如果数据为4字节浮点数,需要转化数据,使用struct.pack、struct.unpack方法把转化为对应格式,其中!为网络字节顺序,h为有符号2字节整型,i为有符号4字节整型,f为4字节浮点型。使用round()方法保留位数。上面可实现存入2字节有符号整型、4字节有符号整型、4字节浮点型读取写入。