c# 从地址拷贝byte_C#工控上位机系列(7)- Modbus TCP通信

客户需要一个电子看板,类似一个电视大小的, 可以显示生产的型号,单号数量等信息. 电子看板是用Modbus TCP通讯的. 生产线每完成一件产品的测试,扫码打包后, 实际产量要增加1, 所以要和生产数据库连接起来

431e350b2be3425e5c22203993e59697.png

下载一个开源的C# Modbus的工具 https://github.com/stephan1827/modbusTCP-DotNET

里面关键代码就是构建Modbus TCP的Header

报文头 报文的序列号2字节, 00 00表示ModbusTCP协议,数据长度2字节,设备地址1字节,

功能码为1字节,寄存器地址2字节,读取长度2字节

Modbus的操作对象有四种:线圈、离散输入、保持寄存器、输入寄存器。对象Coil线圈可读可写DiscreteInputs离散量只读InputRegister输入寄存器只读HoldingRegiste保持寄存器可读可写//功能码private const byte fctReadCoil = 1;        private const byte fctReadDiscreteInputs = 2;        private const byte fctReadHoldingRegister = 3;        private const byte fctReadInputRegister = 4;        private const byte fctWriteSingleCoil = 5;        private const byte fctWriteSingleRegister = 6;        private const byte fctWriteMultipleCoils = 15;        private const byte fctWriteMultipleRegister = 16;        private const byte fctReadWriteMultipleRegister = 23;
  // ------------------------------------------------------------------------        // Create modbus header for read action        private byte[] CreateReadHeader(ushort id, byte unit, ushort startAddress, ushort length, byte function)        {            byte[] data = new byte[12];            byte[] _id = BitConverter.GetBytes((short)id);            data[0] = _id[1];    // Slave id high byte            data[1] = _id[0];// Slave id low byte            data[5] = 6;// Message size ,数据长度            data[6] = unit;// Slave address 设备地址            data[7] = function;// Function code 功能码            byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));            data[8] = _adr[0];// Start address 寄存器地址            data[9] = _adr[1];// Start address            byte[] _length = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)length));            data[10] = _length[0];// Number of data to read 读取长度            data[11] = _length[1];// Number of data to read            return data;        }        // ------------------------------------------------------------------------        // Create modbus header for write action        private byte[] CreateWriteHeader(ushort id, byte unit, ushort startAddress, ushort numData, ushort numBytes, byte function)        {            byte[] data = new byte[numBytes + 11];            byte[] _id = BitConverter.GetBytes((short)id);            data[0] = _id[1];// Slave id high byte            data[1] = _id[0];// Slave id low byte            byte[] _size = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)(5 + numBytes)));            data[4] = _size[0];// Complete message size in bytes            data[5] = _size[1];// Complete message size in bytes            data[6] = unit;// Slave address            data[7] = function;// Function code            byte[] _adr = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)startAddress));            data[8] = _adr[0];// Start address            data[9] = _adr[1];// Start address            if (function >= fctWriteMultipleCoils)            {                byte[] _cnt = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder((short)numData));                data[10] = _cnt[0];// Number of bytes                data[11] = _cnt[1];// Number of bytes                data[12] = (byte)(numBytes - 2);            }            return data;        }

了解了ModBus TCP协议后,我们看看怎么来读写寄存器的例子

 try            {                                // Create new modbus master and add event functions                MBmaster = new Master("192.168.8.1", 502, true);                MBmaster.OnResponseData += new ModbusTCP.Master.ResponseData(MBmaster_OnResponseData);                MBmaster.OnException += new ModbusTCP.Master.ExceptionData(MBmaster_OnException);                  取得工人人数等信息                ReadHoldingRegister();                lblMsg.Text = "连接成功";                            }            catch (SystemException error)            {                MessageBox.Show(error.Message);                lblMsg.Text = error.Message;            }
  // ------------------------------------------------------------------------        // read holding register        // 工人人数,计划数量,实际产量,已耗时长,已耗时长显示保留小数位数 存在地址1到6        //         // ------------------------------------------------------------------------        private void ReadHoldingRegister()        {            ushort ID = 3;  //自己定义的序号            byte unit = Convert.ToByte("1"); //Modus 地址1            ushort StartAddress = 0; //开始地址            UInt16 Length =6; //长度            if (MBmaster != null)            {                MBmaster.ReadHoldingRegister(ID, unit, StartAddress, Length); //异步方法            }         }
 private void MBmaster_OnResponseData(ushort ID, byte unit, byte function, byte[] values)        {            // ------------------------------------------------------------------            // Seperate calling threads            if (this.InvokeRequired)            {                this.BeginInvoke(new Master.ResponseData(MBmaster_OnResponseData), new object[] { ID, unit, function, values });                return;            }            // ------------------------------------------------------------------------            // Identify requested data            switch (ID)            {                case 3:                    //"Read holding register";                    //根据返回值数组大小,来判断哪个数据                    int[] word = ConvertBytesToWords(values);                    if(word.Length==6)                    {                        Console.WriteLine("return ActualCnt=" + ActualCnt);                        WorkerCnt = word[0];                        PlanCnt = word[1];                        ActualCnt = word[2];                        txtWorkerCnt.Text = WorkerCnt.ToString();                        txtActual.Text = ActualCnt.ToString();                        txtPlanCnt.Text = PlanCnt.ToString();                        txtLeftCnt.Text = (PlanCnt - ActualCnt).ToString();                    }                                       break;                case 8:                    //grpData.Text = "Write multiple register";                    break;            }        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值