ModBus协议详解:从基础概念到C#实现RTU与TCP通讯

ModBus协议是莫迪康公司为了让PLC之间进行数据通信而设计出来的协议。它是一种总线协议,是一种一对多,上下级的关系。

它的应用广泛,具有免费开源,操作简单的有点,并且可以兼容串口和网络通讯,兼容也不错。

数据类型:输入布尔(输入线圈),输入寄存器,输出布尔(输出线圈),输出寄存器

布尔就是bool值,寄存器可以是int或者float类型

常用功能码

1、读取

读取输出线圈(Read Coils) 0x01

读取输入线圈 (Read DisCrete Input)0x02,(主机只读)

读取输出寄存器(Read Holding Registers)0x03,

读取输入寄存器(Read Inpute Registers)0x04,(主机只读)

2、写入

写入单个线圈(Write Single Coil)0x05

写入单个寄存器(Write Single Register)0x06

写入多个线圈(Write Multple Coils)0x0F

写入多个寄存器(Write Multple Register)0x10

三种传输类型

1、ModbusRTU,用于串口通信,传递字节码,效率更高

流程是主机向从机发出请求,从站响应请求后,主站才能接收到数据。

主机报文:从站地址+功能码+起始地址+数据长度+校验位(从站地址,功能码占1个字节,起始地址、数据长度、检验位占2个字节)

数据长度可以看做是读取的行数

例如:从机的设备地址是01,功能码是读取输出寄存器03,起始寄存器地址是从第0开始读取,读取的数量是9,得出的报文就是:01 03 00 00 00 09 XX XX

从机报文:从站地址+功能码+数据的字节位数+数据+校验位(从站地址,功能码,数据的字节位数占1个字节,数据、检验位占2个字节)

例如:从机的设备地址是01,功能码是读取输出寄存器03,每次读取4个字节,从机传输的值都是65,得出的报文就是:01 03 04 00 41 00 41 XX XX

2、ModBusAscii,用于串口通信,传递Ascii码

3、ModBusTCP,用于网络传输

4、ModBusUDP,用于网络传输

5、ModBusRTUOverTCP/UDP,串口转网口通信

6、ModBusAsciiOverTCP/UDP,串口转网口通信

使用C#完成ModBus的RTU和TCP通讯

进行测试前需要用到Modbus Slave开启一个ModBus服务

1、RTU通讯(串口通讯)

复制代码
    var modbus = new HslCommunication.ModBus.ModbusRtu();
    modbus.SerialPortInni(cfg => {
        cfg.BaudRate = 9600;
        cfg.PortName = "COM2";
        cfg.Parity = System.IO.Ports.Parity.None;
        cfg.DataBits = 8;
        cfg.StopBits = System.IO.Ports.StopBits.One;

        // 每次写false
        cfg.RtsEnable = false;
    });

    // 设置超时时间
    modbus.ReceiveTimeOut = 5000;

    // 设置起始地址是否从0开始,有些情况是从1开始
    modbus.AddressStartWithZero = true;

    // 设置数据大小端
    modbus.DataFormat = HslCommunication.Core.DataFormat.CDAB;

    // 设置设备地址
    modbus.Station = 1;
    modbus.Crc16CheckEnable = true;
    modbus.IsClearCacheBeforeRead = false;
    var openResult = modbus.Open();
    if(openResult.IsSuccess == false)
    {
        MessageBox.Show("打开ModBus失败");
        return;
    }

    // 读取数据,从第0位开始,读取5个数据
    var readResult = await modbus.ReadInt16Async("0", 5);
    if(readResult.IsSuccess == true)
    {
        this.textBox1.Text = this.textBox1.Text + string.Join(",", readResult.Content) + Environment.NewLine;
    }

    // 继续读取另一个设备地址的Bool类型
    modbus.Station = 2;
    var readBool = await modbus.ReadBoolAsync("5");
    if (readResult.IsSuccess == true)
    {
        this.textBox1.Text = this.textBox1.Text + readBool.Content + Environment.NewLine;
    }

    // 写入数据
    modbus.Station = 1;
    var writeResult = await modbus.WriteAsync("0", (short)90);
    if (writeResult.IsSuccess == true)
    {
        this.textBox1.Text = this.textBox1.Text + "写入成功" + Environment.NewLine;
    }

2、TCP通讯

复制代码
    var modBus = new HslCommunication.ModBus.ModbusTcpNet("127.0.0.1");
    modBus.Port = 502;
    modBus.Station = 1;
    modBus.ConnectTimeOut = 10000;
    modBus.ReceiveTimeOut = 5000;
    modBus.AddressStartWithZero = true;
    modBus.IsStringReverse = false;
    modBus.DataFormat = HslCommunication.Core.DataFormat.CDAB;

    // 读取数据
    var result = await modBus.ReadInt16Async("0");
    if (result.IsSuccess)
    {
         this.textBox1.Text = this.textBox1.Text + result.Content + Environment.NewLine;
    }

    // 写入数据
    var resultWrite = await modBus.WriteAsync("1", 66);
    if (resultWrite.IsSuccess)
    {
        this.textBox1.Text = this.textBox1.Text + "写入成功" + Environment.NewLine;
    }
相关推荐
小白iP代理2 分钟前
动态IP+AI反侦测:新一代爬虫如何绕过生物行为验证?
人工智能·爬虫·tcp/ip
hhh123987_5 分钟前
以太网基础⑥ ZYNQ PS端 基于LWIP的TCP例程测试
网络·网络协议·tcp/ip
Lfsd6 分钟前
根据ip获取地址库
网络·网络协议·tcp/ip
萌新小白的逆袭26 分钟前
《Maven 核心基础笔记(第一天)》
java·开发语言·spring
苦学编程的谢1 小时前
MyBatis_3
java·开发语言·后端·mybatis
go54631584651 小时前
Python点阵字生成与优化:从基础实现到高级渲染技术
开发语言·人工智能·python·深度学习·分类·数据挖掘
猫头虎2 小时前
2025年02月11日 Go生态洞察:Go 1.24 发布亮点全面剖析
开发语言·后端·python·golang·go·beego·go1.19
仰望天空—永强2 小时前
PS 2025【七月最新v26.5】PS铺软件安装|最新版|附带安装文件|详细安装说明|附PS插件
开发语言·图像处理·python·图形渲染·photoshop
寒士obj2 小时前
JVM 内存结构
java·开发语言·jvm
MediaTea2 小时前
Python 库手册:xmlrpc.client 与 xmlrpc.server 模块
开发语言·python