Modbus简介
Modbus协议通常被称为工业化网络的祖父,其支持传统的RS-232、RS-422、RS-485和以太网设备。许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。Modbus协议消息帧格式简单、紧凑、通俗易懂。用户理解和使用简单,厂商容易开发和集成,方便形成工业控制网络。
Modbus通信协议有很多变体,支持串口和以太网版本,其中最著名的有Modbus RTU、Modbus ASCII和Modbus TCP。
- Modbus RTU
建立协议通信,它以二进制格式表示数据,主要用于串行通信。此版本中的消息按空闲时间段划分。RTU 版本遵循的格式是循环冗余校验验证机制,这确保了数据的可靠性。
- Modbus ASCII
为了建立协议通信,使用ASCII字符并且主要在串行通信中实现。此版本中的消息由冒号 (“) 和尾随换行符 (/) 分隔。ASCII 版本遵循的格式是纵向冗余校验以验证机制。
- Modbus TCP
此版本的 Modbus 用于通过TCP/IP 网络通过端口 502 链接进行通信。此变体不需要任何类型的校验和计算,因为较低级别本身提供了这一点。
Modbus协议规定了4个存储区,如下图所示:
Modbus协议同时规定了二十几种功能码,但是常用的只有8种,用于针对存储区的读写,如下图所示:
ProfControl系统中如何使用Modbus通讯?
ProfControl系统中要实现Modbus十分的便捷,支持Modbus RTU、Modbus ASCII和Modbus TCP通讯协议方式的串口设备通讯及以太网通讯(ProfControl系统版本V6.4.1.19及以上版本支持)。下面带大家一起学习下,Modbus通讯实现步骤流程如下示意图所示:
第一步 初始化ModBusCommunication对象实例
/// 初始化ModBusCommunication对象
ModBusCommunication modbus = new ModBusCommunication();
第二步 选择开启ModBus通讯方式
ModBus RTU
/// 开启ModBus RTU通讯协议的串口设备通讯
/// 依次传入串口号名称,波特率,从设备ID号(不传参则默认为1),
/// 数据位(不传参则默认为8位),校验位(不传参则默认为无校验),停止位(不传参则默认为1位)
modbus.InitMasterModBusRTU_SerialPort("COM20",115200);
/// 开启ModBus RTU通讯协议的TCP Client网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusRTU_NetTcp("127.0.0.1",502);
/// 开启ModBus RTU通讯协议的UDP网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusRTU_NetUdp("127.0.0.1",502);
ModBus ASCII
/// 开启ModBus ASCII通讯协议的串口设备通讯
/// 依次传入串口号名称,波特率,从设备ID号(不传参则默认为1),
/// 数据位(不传参则默认为8位),校验位(不传参则默认为无校验),停止位(不传参则默认为1位)
modbus.InitMasterModBusASCII_SerialPort("COM20",115200);
/// 开启ModBus ASCII通讯协议的TCP Client网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusASCII_NetTcp("127.0.0.1",502);
/// 开启ModBus ASCII通讯协议的UDP网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusASCII_NetUdp("127.0.0.1",502);
ModBus TCP
/// 开启ModBus TCP通讯协议的串口设备通讯
/// 依次传入串口号名称,波特率,从设备ID号(不传参则默认为1),
/// 数据位(不传参则默认为8位),校验位(不传参则默认为无校验),停止位(不传参则默认为1位)
modbus.InitMasterModBusTCP_SerialPort("COM20",115200);
/// 开启ModBus TCP通讯协议的TCP Client网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusTCP_NetTcp("127.0.0.1",502);
/// 开启ModBus TCP通讯协议的UDP网络通讯
/// 依次传入网络通讯IP地址、通讯端口、从设备ID号(不传参则默认为1),
modbus.InitMasterModBusTCP_NetUdp("127.0.0.1",502);
第三步 开始读取/写入线圈或寄存器
/// 读取线圈状态
/// 传入待读取线圈起始地址、读取个数,返回读取结果
bool[] result = modbus.ReadCoils(1,10);
/// 读取离散输入状态
/// 传入待读取离散输入起始地址、读取个数,返回读取结果
bool[] result = modbus.ReadInputs(1,10);
/// 读取保持寄存器值
/// 传入待读取保持寄存器起始地址、读取个数,返回读取结果
ushort[] result = modbus.ReadHoldingRegisters(1,10);
/// 读取输入寄存器值
/// 传入待读取输入寄存器起始地址、读取个数,返回读取结果
ushort[] result = modbus.ReadInputRegisters(1,10);
/// 写入单个线圈状态
/// 传入待写入的单个线圈地址、写入状态值,返回写入结果
bool result = modbus.WriteSingleCoil(1,true);
/// 写入单个寄存器值
/// 传入待写入的单个寄存器地址、写入寄存器值,返回写入结果
bool result = modbus.WriteSingleRegister(1,10);
/// 写入多个线圈状态
/// 传入待写入的多个线圈起始地址、写入状态值,返回写入结果
bool result = modbus.WriteMultipleCoils(1,new bool[]{true,false,true,false,true});
/// 写入多个寄存器值
/// 传入待写入的多个寄存器起始地址、写入寄存器值,返回写入结果
bool result = modbus.WriteMultipleRegisters(1,new ushort[]{1,10,100,1000,10000});
第四步 关闭ModBus通讯
modbus.Dispose();
脚本Modbus通讯编程例程
下面我们使用MODBUS调试工具MThings进行模拟仿真Modbus通讯(MThings调试工具下载链接:点击下载)
脚本Modbus通讯编程例程
using System;
using System.Threading;
using ProfControl.PublicAPI;
namespace ProfControl
{
public class test123
{
ModBusCommunication modbusNet;
ModBusCommunication modbusSerial;
public void Main()
{
while (true)
{
if (Tools.IsOpenedProject)
break;
Thread.Sleep(100);
}
/// 初始化Modbus通讯
modbusNet = new ModBusCommunication();
/// 开启Modbus Tcp通讯协议进行网络通讯
modbusNet.InitMasterModBusTCP_NetTcp("127.0.0.1",20000,55);
/// 初始化Modbus通讯
modbusSerial = new ModBusCommunication();
/// 开启Modbus RTU通讯协议进行串口通讯
modbusSerial.InitMasterModBusRTU_SerialPort("COM20",115200,99);
ushort testCnt = 0;
while (true)
{
/// Modbus TCP 网络读取保持寄存器值
ushort[] holdResult = modbusNet.ReadHoldingRegisters(0,10);
/// 打印线圈状态值
if(holdResult != null)
Tools.trace(holdResult);
/// Modbus TCP 网络写入保持寄存器值
modbusNet.WriteSingleRegister(9,testCnt);
/// Modbus RTU 串口读取线圈状态
bool[] coilResult = modbusSerial.ReadCoils(0,10);
/// 打印线圈状态值
if(coilResult != null)
Tools.trace(coilResult);
/// Modbus RTU 串口写入输入寄存器
modbusSerial.WriteSingleRegister(10,testCnt);
testCnt++;
Thread.Sleep(1000);
}
}
public void Kill()
{
if(modbusSerial != null)
modbusSerial.Dispose();
if(modbusNet != null)
modbusNet.Dispose();
}
}
}
Modbus TCP 网络读写寄存器
Modbus RTU 串口读写寄存器