實現效果
實現步驟:
注意:詳細的參數這里就不說明了,自己網上搜即可;
打開GX Works3 創建FX5U項目
系統參數設置PLC的具體型號(我有實物PLC)
設置IP及組態參數
添加通訊設備(這里PLC做客戶端,因此添加:Active連接設備);
設置PLC的端口號、服務器IP、服務器端口號;
當前添加的設備No為1,記住這個參數,后面程序要輸入;
配置完后點擊應用并下載到PLC,下載完要重啟PLC;
下面不廢話,直接上PLC程序;
重點:
在線監控數據
監控D1300是通訊接收數據的起始地址,同時它還存儲對方使用了多少個字節發送數據過來;那么我們要截取數據就要從D1301及以后開始截;
還看到PC只發了5個字符,但是收到卻多了一位(發:SN123;收:SN1239);那么就要處理一下;把多余的字符刪掉;
本項目案例把收到的數據又傳回給PC;經過上面的處理已經拿到完整的數據了,然后置位一下M11就能把數據發給PC,注意每次發送都要觸發一下M11,可以自己改成自動發送;
C#部分
創建一個頁面 SocketPage.xaml
頁面代碼
<Page x:Class="WpfApp4.Views.SocketPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WpfApp4.Views"mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="650"Title="SocketPage" ><Grid><Grid.ColumnDefinitions><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="35"/><RowDefinition Height="35"/><RowDefinition Height="35"/><RowDefinition/></Grid.RowDefinitions><StackPanel Orientation="Horizontal" Grid.Row="0"><Border Height="30" Width="100" Background="White"><TextBlock Text="狀態顯示" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/></Border><Border Height="30" Width="500" Background="#FF0ABEFF"><TextBlock Text="歡迎使用該軟件" x:Name="txtb_serverData" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/></Border></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="1"><Border Height="30" Width="100" Background="White"><TextBlock Text="讀取信息" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/></Border><Border Height="30" Width="500" Background="#FF0ABEFF"><TextBlock Text="------" x:Name="txtb_reData" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/></Border></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="2"><Border Height="30" Width="100" Background="White"><TextBlock Text="連接設備" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/></Border><Border Height="30" Width="500" Background="#FF0ABEFF"><TextBlock Text="127.0.0.0:888" x:Name="txtb_ConnentDevice" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/></Border></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="3"><GroupBox Header="服務器與PLC通訊" Width="250" Height="150" FontSize="20" BorderBrush="#FF0ABEFF" BorderThickness="2"><Grid><Grid.ColumnDefinitions><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><StackPanel VerticalAlignment="Center" Orientation="Horizontal" Grid.Row="0"><Border HorizontalAlignment="Left" ><TextBlock Text="服務器IP: " /></Border><Border HorizontalAlignment="Right" ><TextBox Text="192.168.2.223" x:Name="txb_ServerAdderess" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" Width="145"/></Border></StackPanel><StackPanel VerticalAlignment="Center" Orientation="Horizontal" Grid.Row="1"><Border HorizontalAlignment="Left" ><TextBlock Text="端口號: " /></Border><Border HorizontalAlignment="Right"><TextBox Text="8000" x:Name="txb_Prot" Width="100" TextAlignment="Center"/></Border></StackPanel><Border Grid.Row="2" Width="150" Height="30"><Button x:Name="btn_OpenConnent" Content="打開服務器" Click="Button_OpenProtClick"/></Border></Grid></GroupBox><GroupBox Header="寫數據給PLC" Width="250" Height="150" FontSize="20" BorderBrush="#FF0ABEFF" BorderThickness="2"><Grid><Grid.ColumnDefinitions><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><StackPanel VerticalAlignment="Center" Orientation="Horizontal" Grid.Row="0"><Border HorizontalAlignment="Left" ><TextBlock Text="開 頭: " Width="70"/></Border><Border HorizontalAlignment="Right" ><TextBox Text="SN" x:Name="txb_WriteSN" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" Width="145"/></Border></StackPanel><StackPanel VerticalAlignment="Center" Orientation="Horizontal" Grid.Row="1"><Border HorizontalAlignment="Left" ><TextBlock Text="序列號: " Width="70"/></Border><Border HorizontalAlignment="Right"><TextBox Text="123456789" x:Name="txb_WriteNume" Width="145" TextAlignment="Center" FontSize="16"/></Border></StackPanel><Border Grid.Row="2" Width="150" Height="30"><Button x:Name="btn_WriteDevice" Content="寫入" Click="btn_WriteDevice_Click"/></Border></Grid></GroupBox></StackPanel></Grid>
</Page>
頁面后臺代碼
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;namespace WpfApp4.Views
{/// <summary>/// SocketPage.xaml 的交互邏輯/// </summary>public partial class SocketPage : Page{public SocketPage(){InitializeComponent();}/// <summary>/// 打開/關閉連接/// </summary>bool isConnent = false;/// <summary>/// 服務器已創建/// </summary>bool isOpenConnent = false;/// <summary>/// 觸發寫入/// </summary>bool btn_Write = false;//第一步:調用socket()函數創建一個用于通信的套接字private Socket listenSocket;//字典集合:存儲IP和Socket的集合private Dictionary<string, Socket> OnLineList = new Dictionary<string, Socket>();//編碼格式Encoding econding = Encoding.Default;private void Button_OpenProtClick(object sender, EventArgs e){if (isConnent){MessageBox.Show("服務器已開啟,請勿重復點擊!");return;}if (!isOpenConnent){//第一步:調用socket()函數創建一個用于通信的套接字listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);isOpenConnent = true;}//第二步:給已經創建的套接字綁定一個端口號,這一般通過設置網絡套接口地址和調用Bind()函數來實現IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(this.txb_ServerAdderess.Text.Trim()), int.Parse(this.txb_Prot.Text.Trim()));try{listenSocket.Bind(endPoint);}catch (Exception ex){MessageBox.Show("服務器開啟失敗:" + ex.Message, "開啟服務器");//listenSocket.Shutdown(SocketShutdown.Both);//listenSocket.Close();//MessageBox.Show("關閉服務器中......");isOpenConnent = false;return;}//第三步:調用listen()函數使套接字成為一個監聽套接字listenSocket.Listen(10);//ShowMessage("服務器開啟成功");MessageBox.Show("服務器開啟成功");isConnent = true;this.Dispatcher.Invoke(new Action(() =>{txtb_serverData.Text = "服務器開啟成功!等待客戶端連接中......";btn_OpenConnent.Background = new SolidColorBrush(Colors.Green);}));if (isOpenConnent){//開啟一個線程監聽Task.Run(new Action(() =>{ListenConnection();}));}}private void ListenConnection(){try{while (true){Socket clientSocket = listenSocket.Accept();string ip = clientSocket.RemoteEndPoint.ToString();//MessageBox.Show(ip + "上線了");this.Dispatcher.Invoke(new Action(() =>{txtb_ConnentDevice.Text = "當前連接設備:" + ip;}));Task.Run(() => ReceiveMsg(clientSocket));Task.Run(() => WriteDeviceMsg(clientSocket));}}catch (Exception){throw;}}/// <summary>/// 接收方法/// </summary>/// <param name="clientSocket"></param>private void ReceiveMsg(Socket clientSocket){try{// // 接收數據byte[] bytesToUse = new byte[60];int numberOfBytesRec = clientSocket.Receive(bytesToUse);string returndata = Encoding.ASCII.GetString(bytesToUse, 0, numberOfBytesRec);//Console.WriteLine("從客戶端收到: " + returndata);this.Dispatcher.Invoke(new Action(() =>{txtb_serverData.Text = "從客戶端收到: " + returndata;}));while (true){numberOfBytesRec = clientSocket.Receive(bytesToUse);returndata = Encoding.ASCII.GetString(bytesToUse, 0, numberOfBytesRec);Thread.Sleep(10);this.Dispatcher.Invoke(new Action(() =>{txtb_reData.Text = returndata;txtb_serverData.Text = "從客戶端收到: " + returndata;}));//Console.WriteLine("從客戶端收到: " + returndata);Thread.Sleep(1000);}}catch (Exception ex){MessageBox.Show("接收報錯:" + ex.Message);}}private void WriteDeviceMsg(Socket clientSocket){// 發送數據回客戶端string response = "Hello from server";byte[] msg = Encoding.ASCII.GetBytes(response);try{while (true){this.Dispatcher.Invoke(new Action(() =>{response = txb_WriteSN.Text.ToString() + txb_WriteNume.Text.ToString();msg = Encoding.ASCII.GetBytes(response);}));if (btn_Write){clientSocket.Send(msg);//Console.WriteLine("發送到客戶端: " + response);btn_Write = false;}Thread.Sleep(1000);}}catch (Exception){throw;}}/// <summary>/// 消息發送/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_WriteDevice_Click(object sender, EventArgs e){btn_Write = true;return;}}
}
注意:要把當前連接PLC的網卡設置成服務器IP
最后啟動測試就可以了;