写一个modbus rtu代码示例
时间: 2023-09-02 22:08:43 浏览: 43
好的,以下是一个基于 Python 编写的 Modbus RTU 读取和写入示例代码:
```python
import serial
import struct
# 串口初始化设置
ser = serial.Serial()
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
ser.timeout = 2 # 读取数据超时时间
ser.port = '/dev/ttyUSB0' # 串口号
# Modbus 函数码
READ_COILS = 0x01 # 读取线圈状态
READ_INPUT_BITS = 0x02 # 读取输入状态
READ_HOLDING_REGS = 0x03 # 读取保持寄存器
READ_INPUT_REGS = 0x04 # 读取输入寄存器
WRITE_SINGLE_COIL = 0x05 # 写单个线圈
WRITE_SINGLE_REG = 0x06 # 写单个寄存器
WRITE_MULTIPLE_COILS = 0x0F # 写多个线圈
WRITE_MULTIPLE_REGS = 0x10 # 写多个寄存器
# CRC 校验
def calculate_crc(data):
crc = 0xFFFF
for bit in data:
crc ^= bit
for i in range(8):
if crc & 0x0001:
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return crc
# 读取单个保持寄存器
def read_holding_register(slave_addr, register_addr):
data = [slave_addr, READ_HOLDING_REGS, (register_addr >> 8) & 0xFF, register_addr & 0xFF, 0x00, 0x01]
crc = calculate_crc(data)
data += [crc & 0xFF, (crc >> 8) & 0xFF]
ser.write(data)
res = ser.read(5)
if len(res) != 5:
return None
_, _, length, value1, value2 = struct.unpack('>BBBHBB', res)
if length != 2:
return None
return (value1 << 8) + value2
# 写单个保持寄存器
def write_holding_register(slave_addr, register_addr, value):
data = [slave_addr, WRITE_SINGLE_REG, (register_addr >> 8) & 0xFF, register_addr & 0xFF, (value >> 8) & 0xFF, value & 0xFF]
crc = calculate_crc(data)
data += [crc & 0xFF, (crc >> 8) & 0xFF]
ser.write(data)
res = ser.read(8)
if len(res) != 8:
return False
_, _, _, addr1, addr2, value1, value2, _ = struct.unpack('>BBBBBBBB', res)
if addr1 != ((register_addr >> 8) & 0xFF) or addr2 != (register_addr & 0xFF) or value1 != ((value >> 8) & 0xFF) or value2 != (value & 0xFF):
return False
return True
```
这段代码实现了两个函数,分别是 read_holding_register 和 write_holding_register,用于读取和写入一个单个保持寄存器的值。其中,calculate_crc 函数用于计算 Modbus RTU 的 CRC 校验值。
使用时,只需要根据实际情况修改串口号和 Modbus 从机地址、寄存器地址和数据即可。例如:
```python
read_value = read_holding_register(0x01, 0x03)
write_result = write_holding_register(0x01, 0x06, 0x1234)
```