前言:最近在做一个项目,需要使用ModBus RTU与PLC进行通讯,现在将使用过程记录,以便备查。
一、什么是ModBus通讯协议
Modbus协议是应用于电子控制器上的一种通用语言,此协议支持传统的RS-232、RS-422、RS-485和以太网设备。
ModBus功能码
01 | READ COIL STATUS |
02 | READ INPUT STATUS |
03 | READ HOLDING REGISTER |
04 | READ INPUT REGISTER |
05 | WRITE SINGLE COIL |
06 | WRITE SINGLE REGISTER |
15 | WRITE MULTIPLE COIL |
16 | WRITE MULTIPLE REGISTER |
二、ModBus通讯协议的.Net实现
因为实现并不困难,网上有许多网友自己的实现,但在这里我推荐一个github的开源实现类库:NModBus4,github地址:https://github.com/NModbus4/NModbus4。针对TCP、UDP、RTU等的ModBus通讯方式都有实现。
读写方法:
方法名 | 作用 | 所需参数 | 返回值 | 对应功能码 |
ReadCoils | 读取DO的状态 | 从站地址(8位) byte slaveAddress 起始地址(16位)
ushort startAddress 读取数量(16位) ushort numberOfPoints |
bool[] | 01 |
ReadInputs | 读取DI的状态 | 从站地址(8位) byte slaveAddress 起始地址(16位)
ushort startAddress 读取数量(16位) ushort numberOfPoints |
bool[] | 02 |
ReadHoldingRegisters | 读取AO的值 | 从站地址(8位) byte slaveAddress 起始地址(16位) ushort startAddress 读取数量(16位) ushort numberOfPoints |
ushort[] | 03 |
ReadInputRegisters | 读取AI的值 | 从站地址(8 位) byte slaveAddress 起始地址(16位)
ushort startAddress 读取数量(16位) ushort numberOfPoints |
ushort[] | 04 |
WriteSingleCoil | 写入值到DO | 从站地址(8位) byte slaveAddress 线圈地址(16位) ushort coilAddress 写入值(布尔型) bool value |
无返回值 | 05 |
WriteSingleRegister | 写入值到AO | 从站地址(8位) byte slaveAddress 寄存器地址(16位) ushort registerAddress 写入值(16位) ushort value |
无返回值 | 06 |
WriteMultipleCoils | 写多线圈寄存器 | 从站地址(8位) byte slaveAddress 起始地址(16位) ushort startAddress 写入值(布尔型数组) bool[] data |
无返回值 | 15 |
WriteMultipleRegisters | 写多个保持寄存器 | 从站地址(8位) byte slaveAddress
起始地址(16位) ushort startAddress, 寄存器值(16位整型数组) ushort[] data |
无返回值 | 16 |
ReadWriteMultipleRegisters | 读写多个保持寄存器 | 从站地址(8位) byte slaveAddress 读起始地址(16位) ushort startReadAddress
读取数量(16位) ushort numberOfPointsToRead, 写入起始地址(16位) ushort startWriteAddress, 写入值(16位整型数组) ushort[] writeData |
ushort[] | 23 |
每个方法都有各自的异步方法实现。
这里以RTU展示其使用方法:
1 /// <summary>
2 /// 创建 ModBus RTU 连接
3 /// </summary>
4 /// <param name="portName">端口号</param>
5 /// <param name="baudRate">波特率</param>
6 /// <param name="parity">奇偶校验位</param>
7 /// <param name="dataBits">数据位</param>
8 /// <param name="stopBits">停止位</param>
9 /// <returns></returns>
10 public IModbusSerialMaster CreateModBusRtuConnection(string portName,int baudRate,Parity parity,int dataBits,StopBits stopBits)
11 {
12 return CreateModBusRtuConnect(new SerialPort(portName, baudRate, parity, dataBits, stopBits));
13 }
14
15 public IModbusSerialMaster CreateModBusRtuConnection(SerialPort serialPort)
16 {
17 IModbusSerialMaster master = null;
18 if (!serialPort.IsOpen)
19 {
20 try
21 {
22 serialPort.Open();
23 }
24 catch (Exception e)
25 {
26 throw e;
27 }
28 }
29 try
30 {
31 master = ModbusSerialMaster.CreateRtu(serialPort);
32 ///同时也可以配置master的一些参数
33 master.Transport.ReadTimeout = 100;//读取数据超时100ms
34 master.Transport.WriteTimeout = 100;//写入数据超时100ms
35 master.Transport.Retries = 3;//重试次数
36 master.Transport.WaitToRetryMilliseconds = 10;//重试间隔
37
38 }
39 catch(Exception e)
40 { throw e;
41 }
42 return master;
43 }
44 }
来源:oschina
链接:https://my.oschina.net/u/4323755/blog/4471299