首頁>技術>

客戶需要一個電子看板,類似一個電視大小的, 可以顯示生產的型號,單號數量等資訊. 電子看板是用Modbus TCP通訊的. 生產線每完成一件產品的測試,掃碼打包後, 實際產量要增加1, 所以要和生產資料庫連線起來

下載一個開源的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;            }        }

16
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 跟光磊學Java開發-Java併發程式設計基礎