C# MODBUS RTU 通信 第二章

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档



一、 不使用库

写单个寄存器

        public void SendModbusData(SerialPort serialPort, byte deviceAddress, ushort registerAddress, ushort registerValue)
        {
            byte[] modbusFrame = new byte[8];
            modbusFrame[0] = deviceAddress; // 设备地址
            modbusFrame[1] = 0x06; // 功能码 (写单个寄存器)
            modbusFrame[2] = (byte)(registerAddress >> 8); // 寄存器地址高字节
            modbusFrame[3] = (byte)(registerAddress & 0xFF); // 寄存器地址低字节
            modbusFrame[4] = (byte)(registerValue >> 8); // 寄存器值高字节
            modbusFrame[5] = (byte)(registerValue & 0xFF); // 寄存器值低字节
                                                           // 计算CRC
            ushort crc = CalculateCRC(modbusFrame, 6);
            modbusFrame[6] = (byte)(crc & 0xFF); // CRC低字节
            modbusFrame[7] = (byte)(crc >> 8); // CRC高字节
                                               // 发送数据
            if (serialPort.IsOpen)
            {
                serialPort.Write(modbusFrame, 0, modbusFrame.Length);
            }
            else
            {
                throw new InvalidOperationException("串口未打开");
            }
        }
     

数据校验

   private ushort CalculateCRC(byte[] data, int length)
        {
            ushort crc = 0xFFFF;
            for (int pos = 0; pos < length; pos++)
            {
                crc ^= (ushort)data[pos];
                for (int i = 8; i != 0; i--)
                {
                    if ((crc & 0x0001) != 0)
                    {
                        crc >>= 1;
                        crc ^= 0xA001;
                    }
                    else
                    {
                        crc >>= 1;
                    }
                }
            }
            return crc;
        }

读取单个寄存器

        public void SendModbusQuery(SerialPort serialPort, byte deviceAddress, ushort registerAddress)
        {
            byte[] modbusFrame = new byte[8];
            modbusFrame[0] = deviceAddress; // 设备地址
            modbusFrame[1] = 0x03; // 功能码 (读取单个寄存器)
            modbusFrame[2] = (byte)(registerAddress >> 8); // 寄存器地址高字节
            modbusFrame[3] = (byte)(registerAddress & 0xFF); // 寄存器地址低字节
            modbusFrame[4] = 0x00; // 读取一个寄存器,寄存器数目高字节
            modbusFrame[5] = 0x01; // 读取一个寄存器,寄存器数目低字节
                                   // 计算CRC
            ushort crc = CalculateCRC(modbusFrame, 6);
            modbusFrame[6] = (byte)(crc & 0xFF); // CRC低字节
            modbusFrame[7] = (byte)(crc >> 8); // CRC高字节
                                               // 发送数据
            if (serialPort.IsOpen)
            {
                serialPort.Write(modbusFrame, 0, modbusFrame.Length);
            }
            else
            {
                throw new InvalidOperationException("串口未打开");
            }
        }

二、使用NModbu库

首先,你需要安装 NModbus 库。可以通过NuGet包管理器来安装:

1. 引入必要的命名空间

代码如下(示例):

using System;
using System.IO.Ports;
using NModbus;
using NModbus.Serial;

2.初始化串口和MODBUS主站:

代码如下(示例):

class Program
{
    static void Main(string[] args)
    {
        // 配置串口参数
        string portName = "COM3"; // 串口号
        int baudRate = 9600;      // 波特率
        Parity parity = Parity.None; // 校验位
        int dataBits = 8;         // 数据位
        StopBits stopBits = StopBits.One; // 停止位

        // 创建串口对象
        using (SerialPort serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits))
        {
            // 打开串口
            serialPort.Open();

            // 创建MODBUS主站
            IModbusSerialMaster master = new ModbusSerialMaster(serialPort, ModbusSerialTransportMode.Rtu);

            // 设置超时时间
            master.Transport.ReadTimeout = 500;
            master.Transport.WriteTimeout = 500;

            // 发送请求并接收响应
            SendAndReceive(master);
        }
    }

3.发送和接收请求:

static void SendAndReceive(IModbusSerialMaster master)
{
    try
    {
        // 目标设备地址
        byte slaveId = 0x01;

        // 读取保持寄存器
        ushort startAddress = 0x0001; // 起始地址
        ushort numberOfPoints = 2;    // 读取的寄存器数量

        // 发送读保持寄存器请求
        ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numberOfPoints);

        // 输出读取的寄存器值
        Console.WriteLine("Read Holding Registers:");
        for (int i = 0; i < registers.Length; i++)
        {
            Console.WriteLine($"Register {startAddress + i}: {registers[i]}");
        }

        // 写单个保持寄存器
        ushort writeAddress = 0x0001; // 要写入的寄存器地址
        ushort writeValue = 0x0001;   // 要写入的值

        // 发送写单个保持寄存器请求
        master.WriteSingleRegister(slaveId, writeAddress, writeValue);

        Console.WriteLine($"Wrote value {writeValue} to register {writeAddress}");

        // 广播复位命令
        byte broadcastAddress = 0x00;
        ushort resetAddress = 0x0000; // 要写入的寄存器地址
        ushort resetValue = 0x0001;   // 要写入的值

        // 发送广播复位命令
        master.WriteSingleRegister(broadcastAddress, resetAddress, resetValue);

        Console.WriteLine($"Broadcast reset command sent to all devices");

    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值