网站管理系统哪个好,Wordpress做什么网站赚钱,百度关键词排名查询接口,wordpress和discuz织梦1、客户端选择
客户端可以是一个程序或一个设备#xff0c;这里我以C#WINFORM程序来实现客户机与PLC的Modbustcp服务器通信#xff0c;开发环境是VS2019#xff0c;.NET Framework版本是4.7.2
2、创建winform程序 3、引入Nmodbus4协议
找到项目#xff0c;找到引用… 1、客户端选择
客户端可以是一个程序或一个设备这里我以C#WINFORM程序来实现客户机与PLC的Modbustcp服务器通信开发环境是VS2019.NET Framework版本是4.7.2
2、创建winform程序 3、引入Nmodbus4协议
找到项目找到引用右键“管理nuget程序”在下面对话框操作 4、界面布局如下
布局中用到的是下拉框combobox文本框textbox按钮button标签label 这个IP地址和端口号是与这里对应 5、窗体定义两个变量并引入对应的命令空间 ModbusIpMaster master null;//modbus对象 TcpClient tcpClient null;//tcp客户端对象 6、连接按钮代码 private void btnOpen_Click(object sender, EventArgs e){string ip txtIPAddress.Text.Trim();bool t IsIP(ip);if (t){try{int port int.Parse(txtPort.Text.Trim());tcpClient new TcpClient();tcpClient.Connect(ip, port);//连接到主机master ModbusIpMaster.CreateIp(tcpClient);//Ip 主站master.Transport.ReadTimeout 1000;//读超时master.Transport.WriteTimeout 1000;//写超时master.Transport.Retries 3;//尝试重复连接次数master.Transport.WaitToRetryMilliseconds 200;//尝试重复连接间隔lblMessage.Text 连接成功;btnOpen.Enabled false;}catch (Exception ex){MessageBox.Show(连接失败 ex.Message);}}else{MessageBox.Show(无效的ip地址);}} 7、读取的代码--ushort类型
本例子中只用到了读取保存寄存器这个功能码即ReadHoldingRegisters(从站地址开始地址寄存器数量) /// summary/// 读取/// /summary/// param namesender/param/// param namee/paramprivate void myread_Click(object sender, EventArgs e){//由于NModbus4读取到寄存器的数据都是ushort类型//功能码string readType cboReadTypes.Text.Trim();//从站地址byte slaveAddr byte.Parse(txtRSlaveId.Text.Trim());//开始地址ushort startAddr ushort.Parse(txtRStartAddress.Text.Trim());//读取数量ushort readCount ushort.Parse(txtRCount.Text.Trim());switch (readType){case 读线圈:bool[] blVals master.ReadCoils(slaveAddr, startAddr, readCount);txtReadDatas1.Text string.Join(,, blVals.Select(b b ? 1 : 0));break;case 读输入线圈:bool[] blInputVals master.ReadInputs(slaveAddr, startAddr, readCount);txtReadDatas1.Text string.Join(,, blInputVals.Select(b b ? 1 : 0));break;case 读保持寄存器://情况1ushort到ushort类型即读取无符号的整数如2389处理方法是原封不动//ushort[] uDatas master.ReadHoldingRegisters(slaveAddr, startAddr, readCount);//txtReadDatas.Text string.Join(,, uDatas);//功能码string dataType cmddatatype.Text.Trim();switch (dataType){case ushort://利用token循环读取ushortctsRead new CancellationTokenSource();Task.Run(new Action(() {ReadUshortFromPLC(slaveAddr, startAddr, readCount);}), ushortctsRead.Token);break;case short://利用token循环读取shortctsRead new CancellationTokenSource();Task.Run(new Action(() {ReadShortFromPLC(slaveAddr, startAddr, readCount);}), shortctsRead.Token);break;case float://利用token循环读取floatctsRead new CancellationTokenSource();Task.Run(new Action(() {ReadFloatFromPLC(slaveAddr, startAddr, readCount);}), floatctsRead.Token);break;} break;case 读输入寄存器:ushort[] uDatas1 master.ReadInputRegisters(slaveAddr, startAddr, readCount);txtReadDatas1.Text string.Join(,, uDatas1);break;}}
这里要注意
NModbus4读取到寄存器的数据都是ushort类型
NModbus4读取到寄存器的数据都是ushort类型
代码中用到ReadUshortFromPLC方法ReadShortFromPLC方法ReadFloatFromPLC方法在本文最后链接都会提供
运行程序连接成功读取数据 注意这里从站地址一般都是1除非你改了开始地址是0表示寄存器的起始地址数量是3表示读取3个寄存器数量也就是前面3个变量m1-speedm1-duarorm1-level 这里为什么数量不能是4因为第4个变量是real它占2个寄存器即占4个字节它不是ushort类型这里地址也不能是%DB3.DBW4这种写法这不是S7协议读取变量是MODBUS读取寄存器两者不一样的别糊涂了各位长老。
8、读取的代码--float类型 很多人搞不清楚这个开始地址和数量这个开始地址是Modbus的地址Modbus地址编号从0开始因此8个变量的地址就是01234567数量是指要读取的寄存器个数word占一个real占2个这里很难理解比较绕比较晕一个是PLC地址一个是MODBUS地址
我们要读的温度是第3个寄存器它是real类型占2个寄存器数量
9、写入的代码--ushort类型 /// summary/// 写入/// /summary/// param namesender/param/// param namee/paramprivate void btnWrite_Click(object sender, EventArgs e){//功能码string writeType cboWriteTypes.Text.Trim();//从站地址byte slaveAddr byte.Parse(txtWSlaveId.Text.Trim());//开始地址ushort startAddr ushort.Parse(txtWStartAddress.Text.Trim());//数量//实际数量string objWriteVals ;string dataType cmddatatype2.Text.Trim();switch (dataType){case ushort:objWriteVals txtWriteDatas1.Text.Trim();break;case short:objWriteVals txtWriteDatas2.Text.Trim();break;case float:objWriteVals txtWriteDatas3.Text.Trim();break;}ushort writeCount ushort.Parse(txtWCount.Text.Trim()); ushort objWCount (ushort)objWriteVals.Split(,).Length;//实际数量与要求数量不一致不允许操作if (writeCount ! objWCount){MessageBox.Show(写入值的数量不正确!);return;}string vals objWriteVals;switch (writeType){case 写单线圈:bool blVal vals 1 ? true : false;try{master.WriteSingleCoil(slaveAddr, startAddr, blVal);MessageBox.Show(【单线圈】写入成功!);}catch (Exception ex){MessageBox.Show(ex.Message);}break;case 写单保持寄存器:ushort uVal01 ushort.Parse(vals);try{master.WriteSingleRegister(slaveAddr, startAddr, uVal01);MessageBox.Show(【单保持寄存器】写入成功!);}catch (Exception ex){MessageBox.Show(ex.Message);}break;case 写多线圈:bool[] blVals vals.Split(,).Select(s s 1 ? true : false).ToArray();//bool数组try{master.WriteMultipleCoils(slaveAddr, startAddr, blVals);MessageBox.Show(【多线圈】写入成功!);}catch (Exception ex){MessageBox.Show(ex.Message);}break;case 写多保持寄存器:try{//功能码//string dataType cmddatatype2.Text.Trim();switch (dataType){case ushort:情况1写入无符号的整数即写入ushort数据如写入3344ushort[] uVals01 vals.Split(,).Select(s ushort.Parse(s)).ToArray();master.WriteMultipleRegisters(startAddr, uVals01);break;case short://情况2写入有符号的整数即写入short数据如写入-133-6598等处理方法是short[]byte[]ushort[]情况2包括了情况1 short[] uVals02 vals.Split(,).Select(s short.Parse(s)).ToArray();byte[] y2 ByteArrayLib.GetByteArrayFromShortArray(uVals02);ushort[] ushorts2 UShortLib.GetUShortArrayFromByteArray(y2);master.WriteMultipleRegisters(startAddr, ushorts2);MessageBox.Show(【short类型数据】写入成功!);break;case float://情况3写入有符号的小数即写入float数据如写入-6.3-2.6556.89351-465等处理方法是float[]byte[]ushort[]情况3包括了情况2和情况1 float[] uVals03 vals.Split(,).Select(s float.Parse(s)).ToArray();byte[] y3 ByteArrayLib.GetByteArrayFromFloatArray(uVals03);ushort[] ushorts3 UShortLib.GetUShortArrayFromByteArray(y3);master.WriteMultipleRegisters(startAddr, ushorts3);MessageBox.Show(【float类型数据】写入成功!);break;}情况2写入有符号的整数即写入short数据如写入-133-6598等处理方法是short[]byte[]ushort[]情况2包括了情况1 //short[] uVals02 vals.Split(,).Select(s short.Parse(s)).ToArray();//byte[] y ByteArrayLib.GetByteArrayFromShortArray(uVals02);//ushort[] ushorts UShortLib.GetUShortArrayFromByteArray(y);//master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);情况3写入有符号的小数即写入float数据如写入-6.3-2.6556.89351-465等处理方法是float[]byte[]ushort[]情况3包括了情况2和情况1 //float[] uVals02 vals.Split(,).Select(s float.Parse(s)).ToArray();//byte[] y ByteArrayLib.GetByteArrayFromFloatArray(uVals02);//ushort[] ushorts UShortLib.GetUShortArrayFromByteArray(y);//master.WriteMultipleRegisters(slaveAddr, startAddr, ushorts);MessageBox.Show(【多保持寄存器】写入成功!);}catch (Exception ex){MessageBox.Show(ex.Message);}break;}} 写入成功同时读取的也是刚才写的值在博途的监控表中看到 10、写入的代码--float类型 写入负数 11、小结
客户端创建tcp client对象然后modbus利用tcp对象创建modbus通信然后通过不同数据类型读写PLC数据成功了
代码链接
链接https://pan.baidu.com/s/1aCqv3eSX-7SXAdGtrGNpTw 提取码kyqo