ProfControl系统实现Modbus通讯
18021520013
·
创建日期: 2022-05-30 01:30:58
·
2
1
0
65

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 串口读写寄存器