C#上位机与三菱PLC的通信11---开发自己的通讯工具软件(WPF版)

1、先看颜值

2、开始干

1、创建项目

2、引入前面的通讯库

 创建目录将前面生成的通讯库dll文件复制到项目的目录

本项目引入dll文件

 

 3、创建命令基类

RelayCommand.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MitsubishiMcToolWPF.Common
{
    /// <summary>
    /// 命令实现类
    /// </summary>
    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        /// <summary>
        /// 要执行的操作
        /// </summary>
        private Action<object> executeActions;
        /// <summary>
        /// 是否可以执行的委托
        /// </summary>
        private Func<object, bool> canExecuteFunc;
        /// <summary>
        /// 构造函数 无参构造
        /// </summary>
        public RelayCommand() { }
        /// <summary>
        /// 通过执行的委托构造
        /// </summary>
        /// <param name="execute"></param>
        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }
        /// <summary>
        /// 通过执行的操作与是否可执行的委托
        /// </summary>
        /// <param name="execute">要执行的操作</param>
        /// <param name="canExecute">是否可以被执行</param>
        public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            this.executeActions = execute;
            this.canExecuteFunc = canExecute;
        }

        /// <summary>
        /// 命令是否可以执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            if (canExecuteFunc != null)
                return this.canExecuteFunc(parameter);
            else
                return true;
        }

        /// <summary>
        /// 要执行的操作
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            if (executeActions == null)
                return;
            this.executeActions(parameter);
        }

        /// <summary>
        /// 执行CanExecuteChanged事件
        /// </summary>
        public void OnCanExecuteChanged()
        {
            this.CanExecuteChanged?.Invoke(this, new EventArgs());
        }
    }
}

 4、创建PLC实体类

PLCMemoryModel.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MitsubishiMcToolWPF.Model
{
    /// <summary>
    /// PLC内存模型类
    /// </summary>
    public class PLCMemoryModel
    {
        /// <summary>
        /// 存储区
        /// </summary>
        public string Area { get; set; } = "";
        /// <summary>
        /// 地址
        /// </summary>

        public string Address { get; set; } = "";
        /// <summary>
        /// 数据类型
        /// </summary>

        public string DataType { get; set; } = "";
        /// <summary>
        /// 读取或写入数据
        /// </summary>

        public string Count { get; set; } = "";
    }
}

 5、添加资源字典,即样式文件

CommonResource.xaml完整代码

 <!--读取写入Button按钮样式--> 
 <Style x:Key="ButtonStyle" TargetType="Button">
     <Setter Property="Background" Value="#3F85FF"></Setter>
     <Setter Property="Foreground" Value="White"></Setter>
     <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
     <Setter Property="Margin" Value="5"></Setter>
     <Setter Property="Height" Value="90"></Setter>
     <Setter Property="FontSize" Value="16"></Setter>
     <!--模板的样式-->
     <Setter Property="Template">
         <Setter.Value>
             <!--Button单选按钮样式-->
             <ControlTemplate TargetType="Button">
                 <Grid >
                     <Border Background="{TemplateBinding Background}" CornerRadius="5" >
                         <TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                     </Border>
                 </Grid>
                 <ControlTemplate.Triggers>
                     <!--鼠标放上去时的触发器-->
                     <Trigger Property="IsMouseOver" Value="True">
                         <Setter Property="Background" Value="#1E5FD1" ></Setter>
                     </Trigger>
                 </ControlTemplate.Triggers>

             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>
 
 <!--连接断开按钮样式-->
 <Style x:Key="ConnStyle" TargetType="Button">
     <Setter Property="Background" Value="#3F8666"></Setter>
     <Setter Property="Foreground" Value="White"></Setter>
     <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
     <Setter Property="Margin" Value="5"></Setter>
     <Setter Property="Height" Value="60"></Setter>
     <Setter Property="FontSize" Value="16"></Setter>
     <!--模板的样式-->
     <Setter Property="Template">
         <Setter.Value>
             <!--Button单选按钮样式-->
             <ControlTemplate TargetType="Button">
                 <Grid >
                     <Border Background="{TemplateBinding Background}" CornerRadius="5" >
                         <TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                     </Border>
                 </Grid>
                 <ControlTemplate.Triggers>
                     <!--鼠标放上去时的触发器-->
                     <Trigger Property="IsMouseOver" Value="True">
                         <Setter Property="Background" Value="#1E5FD1" ></Setter>
                     </Trigger>
                 </ControlTemplate.Triggers>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>


 <!--TextBox默认样式-->
 <Style TargetType="{x:Type TextBox}" x:Key="txtTextBoxStyle">
     <Setter Property="Width" Value="150"/>
     <Setter Property="Height" Value="25"/>
     <Setter Property="BorderBrush" Value="#FF105190"/>
     <Setter Property="BorderThickness" Value="1"/>
     <Setter Property="Margin" Value="2,0"/>
     <Setter Property="VerticalContentAlignment" Value="Center"/>
     <Setter Property="Background">
         <Setter.Value>
             <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                 <GradientStop Color="White" Offset="0"/>
                 <GradientStop Color="#FFE4E4E4" Offset="1"/>
             </LinearGradientBrush>
         </Setter.Value>
     </Setter>
 </Style>

 <!--TextBlock默认样式-->
 <Style TargetType="{x:Type TextBlock}" x:Key="txtTextBlockStyle">
     <Setter Property="Margin" Value="1"/>
     <Setter Property="Height" Value="15"/>
 </Style>

 <!--页面下拉框样式-->
 <LinearGradientBrush x:Key="ComboBox.Static.Background" EndPoint="0,1" StartPoint="0,0">
     <GradientStop Color="White" Offset="0"/>
     <GradientStop Color="#FFE4E4E4" Offset="1"/>
 </LinearGradientBrush>
 <SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FF105190"/>

 <!--combox默认样式-->
 <Style x:Key="cboStyle" TargetType="{x:Type ComboBox}">
     <Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/>
     <Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/>
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
     <Setter Property="Width" Value="150"/>
     <Setter Property="Height" Value="25"/>
     <Setter Property="BorderThickness" Value="1"/>
     <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
     <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
     <Setter Property="Padding" Value="6,3,5,3"/>
     <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
     <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
     <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
 </Style>

 

 6、创建viewmodel

viewmodel是视图模型,wpf采用的是mvvm的渲染模式,即控件绑定对象的属性,属性发生更改时,驱动控件的数据显示,而控件动作是由命令command执行

1、模型基类

ViewModelBase.cs代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using static MitsubishiMcToolWPF.MsgBoxWindow;

namespace MitsubishiMcToolWPF.ViewModel
{
    /// <summary>
    /// 视图模型基类
    /// </summary>
    public class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// 属性值发生更改时触发
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;



        /// <summary>
        /// 执行更改
        /// C#5.0中的新特性CallerMemberName
        /// </summary>
        /// <param name="propertyName"></param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        /// <summary>
        /// 成功消息提示
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        public void ShowMessage(string message, string title = "提示", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
        {
            Show(message, title, buttons, CustomMessageBoxIcon.Infomation);
        }

        /// <summary>
        /// 错误消息框
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        public void ShowError(string message, string title = "错误", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
        {
            Show(message, title, buttons, CustomMessageBoxIcon.Error);
        }

        /// <summary>
        /// 询问消息框
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        /// <returns></returns>
        public CustomMessageBoxResult ShowQuestion(string message, string title = "询问", CustomMessageBoxButton buttons = CustomMessageBoxButton.OKCancel)
        {
            return Show(message, title, buttons, CustomMessageBoxIcon.Question);
        }



    }
}

 2、主页模型mainviewmodel

MainViewModel.cs代码

 

using Mitsubishi.Communication.MC.Mitsubishi;
using MitsubishiMcToolWPF.Common;
using MitsubishiMcToolWPF.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MitsubishiMcToolWPF.ViewModel
{
    /// <summary>
    /// 视图模型
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// mctcp对象
        /// </summary>
        A3E mctcp;

        #region 属性

        PLCMemoryModel readPLCModel = SetInitModel();
        /// <summary>
        /// 读取PLC
        /// </summary>
        public PLCMemoryModel ReadPLCModel
        {
            get { return readPLCModel; }
            set
            {
                readPLCModel = ReadPLCModel;
                OnPropertyChanged();//属性通知
            }
        }

        PLCMemoryModel writePLCModel = SetInitModel();
        /// <summary>
        /// 写入PLC
        /// </summary>
        public PLCMemoryModel WritePLCModel
        {
            get { return writePLCModel; }
            set
            {
                writePLCModel = WritePLCModel;
                OnPropertyChanged();
            }
        }
        /// <summary>
        /// 初始化页面参数
        /// </summary>
        /// <returns></returns>
        private static PLCMemoryModel SetInitModel()
        {
            PLCMemoryModel model = new PLCMemoryModel();
            model.Area = "D";
            model.DataType = "short";
            model.Address = "100";
            model.Count = "1";
            return model;
        }

        private string hostName = "192.168.1.7";
        /// <summary>
        /// PLC地址
        /// </summary>
        public string HostName
        {
            get
            {
                return hostName;
            }
            set
            {
                hostName = value;
            }
        }

        private string hostPort = "6000";
        /// <summary>
        /// PLC端口
        /// </summary>
        public string HostPort
        {
            get { return hostPort; }
            set
            {
                hostPort = value;
            }
        }


        /// <summary>
        /// 存储区下拉框数据源
        /// </summary>
        public List<string> CboCustTypes
        {
            get
            {
                return new List<string>() { "D", "X", "Y", "M", "R", "S", "TS" };
            }
        }

        /// <summary>
        /// 数据类型
        /// </summary>
        public List<string> CboCustDatas
        {
            get
            {
                return new List<string>() { "short", "float", "bool" };
            }
        }

        private string readWords = "";
        /// <summary>
        /// 读数结果
        /// </summary>
        public string ReadWords
        {
            get { return readWords; }
            set
            {
                readWords = value;
                OnPropertyChanged();
            }
        }
        private string writeWords = "";
        /// <summary>
        /// 写入数据
        /// </summary>
        public string WriteWords
        {
            get { return writeWords; }
            set
            {
                writeWords = value;
                OnPropertyChanged();
            }
        }

        private string connectWords = "当前未连接";
        /// <summary>
        /// 连接状态
        /// </summary>
        public string ConnectWords
        {
            get { return connectWords; }
            set
            {
                connectWords = value;
                OnPropertyChanged();
            }
        }
        #endregion

        #region 命令

        /// </summary>
        /// <summary>
        ///连接按钮的命令 
        /// </summary>
        public ICommand ConnCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    var name = HostName;
                    var port = HostPort;
                    mctcp = new A3E(name, short.Parse(port));// 创建连接 
                    var result = mctcp.Connect();// 开始连接PLC
                    if (!result.IsSuccessed)
                    {
                        ShowError(result.Message, "错误");
                        return;
                    }
                    ConnectWords = "PLC已连接";
                    ShowMessage("PLC连接成功", "提示");
                });
            }
        }


        /// </summary>
        /// <summary>
        ///断开按钮的命令 
        /// </summary>
        public ICommand CloseCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    if (mctcp == null)
                    {
                        ShowError("PLC没有连接,不能断开", "错误");
                        return;
                    }
                    mctcp = null;
                    ConnectWords = "PLC已断开";
                });
            }
        }


        /// </summary>
        /// <summary>
        /// 读取按钮的命令 
        /// </summary>
        public ICommand ReadCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    ReadWords = "";
                    var d = ReadPLCModel;
                    if (mctcp == null)
                    {
                        ShowError("PLC未连接,不能读取数据", "错误");
                        return;
                    }
                    //内存地址
                    string plcAddr = ReadPLCModel.Area + ReadPLCModel.Address;
                    //读取数量
                    short readCount = short.Parse(ReadPLCModel.Count);
                    //数据类型
                    string dataType = ReadPLCModel.DataType;
                    switch (dataType)
                    {
                        case "short":
                            var datas2 = mctcp.Read<short>(plcAddr, readCount);
                            if (!datas2.IsSuccessed)
                            {
                                ShowMessage(datas2.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas2.Datas);
                            break;
                        case "float":
                            var datas3 = mctcp.Read<float>(plcAddr, readCount);
                            if (!datas3.IsSuccessed)
                            {
                                ShowMessage(datas3.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas3.Datas);
                            break;
                        case "bool":
                            var datas4 = mctcp.Read<bool>(plcAddr, readCount);
                            if (!datas4.IsSuccessed)
                            {
                                ShowMessage(datas4.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas4.Datas);
                            break;
                    }
                });
            }
        }


        /// </summary>
        /// <summary>
        /// 写入按钮的命令处理
        /// </summary>
        public ICommand WriteCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    if (mctcp == null)
                    {
                        ShowError("PLC未连接,不能写入数据", "错误");
                        return;
                    }
                    var d = WritePLCModel;
                    //内存地址
                    string plcAddr = WritePLCModel.Area + WritePLCModel.Address;
                    //写入数量 
                    ushort writeCount = ushort.Parse(WritePLCModel.Count);
                    //数据类型
                    string dataType = WritePLCModel.DataType;
                    //实际数量
                    string objWriteVals = WriteWords;
                    ushort objWCount = (ushort)objWriteVals.Split(',').Length;
                    //实际数量与要求数量不一致,不允许操作
                    if (writeCount != objWCount)
                    {
                        ShowError("写入值的数量不正确!");
                        return;
                    }
                    List<string> vals = objWriteVals.Split(',').ToList();
                    switch (dataType)
                    {
                        case "short":
                            //实际数值转换成list集合 short类型
                            List<short> objshort = new List<short>();
                            vals.ForEach((x) =>
                            {
                                objshort.Add(short.Parse(x));
                            });
                            var finish2 = mctcp.Write<short>(objshort, plcAddr);
                            if (finish2.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                        case "float":
                            //实际数值转换成list集合 float
                            List<float> objfloat = new List<float>();
                            vals.ForEach((x) =>
                            {
                                objfloat.Add(float.Parse(x));
                            });
                            var finish3 = mctcp.Write<float>(objfloat, plcAddr);
                            if (finish3.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                        case "bool":
                            //实际数值转换成list集合bool
                            List<bool> objbool = new List<bool>();
                            vals.ForEach((x) =>
                            {
                                if (x == "1")
                                {
                                    objbool.Add(true);
                                }
                                else
                                {
                                    objbool.Add(false);
                                }
                            });
                            var finish4 = mctcp.Write<bool>(objbool, plcAddr);
                            if (finish4.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                    }
                });
            }
        }
        #endregion

    }
}

7、主界面布局

MainWindow.xaml完整代码

<Window x:Class="MitsubishiMcToolWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MitsubishiMcToolWPF.ViewModel"
        mc:Ignorable="d"   
        FontSize="13" FontFamily="Microsoft YaHei"  ResizeMode="CanMinimize" Title="三菱PLC通讯工具" FontWeight="ExtraLight" WindowStartupLocation="CenterScreen"  Height="450" Width="880" Name="mainWin"  >
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid   ShowGridLines="true">
        <Grid.RowDefinitions>
            <RowDefinition Height="62"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!--第一行标题-->
        <Grid Grid.Row="0" Background="BlanchedAlmond">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Image Grid.Column="0" Source="/imgs/log1.png"  Width="60" Height="60" Margin="20,0" />
            <TextBlock Grid.Column="1"   Text="三菱MC协议通讯调试助手(Qna-3E模式)" FontSize="23" VerticalAlignment="Center"  FontWeight="Bold" />
        </Grid>

        <!--第二行信息-->
        <Grid Grid.Row="1" Margin="0 10 0 0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200"/>
                <ColumnDefinition Width="4"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <!--第一列PLC参数-->
            <StackPanel Grid.Column="0" Margin="20">
                <TextBlock Text="PLC地址"/>
                <TextBox   Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostName}"  />
                <TextBlock Text="端口号" Margin="0,10,0,0"/>
                <TextBox  Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostPort}"  />
                <Button Content="连接" Margin="0,30,0,0" Height="30"   Command="{Binding ConnCommand}"  Style="{StaticResource ConnStyle}" />
                <Button Content="断开" Margin="0,10" Height="30"  Command="{Binding CloseCommand}"  Style="{StaticResource ConnStyle}"/>
                <TextBlock  Text="{Binding ConnectWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Margin="0,10,0,0"  Foreground="Blue"/>
            </StackPanel>
            <!--第二列分隔线-->
            <GridSplitter Grid.Column="1" Background="#4490AC" Width="2" Height="450" Margin="0 -11 0 0"></GridSplitter>
            <!--第三列操作区-->
            <Grid Grid.Column="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="60"/>
                    <RowDefinition Height="80"/>
                    <RowDefinition Height="30"/>
                    <RowDefinition Height="60"/>
                    <RowDefinition Height="80"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="10">
                    <TextBlock     Text="存储区:"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0" ></TextBlock>
                    <ComboBox  ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding  ReadPLCModel.Area}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="数据类型:"  Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding ReadPLCModel.DataType}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding ReadPLCModel.Address}"  Width="100"  Style="{StaticResource  txtTextBoxStyle}" />
                    <TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding ReadPLCModel.Count}"  Width="60" Style="{StaticResource  txtTextBoxStyle}"  />
                    <Button Content="读取" Height="30" Width="100"  Command="{Binding ReadCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}"  />
                </StackPanel>

                <StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock Text="读取结果(多个数据之间用逗号隔开)"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 3 0 9"></TextBlock>
                    <TextBox   Text="{Binding ReadWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"   />
                </StackPanel>

                <StackPanel Orientation="Horizontal"  Grid.Row="2"  Grid.Column="0" Grid.ColumnSpan="2" Background="#4490AC" Width="706" Height="2" Margin="-1,0,0,0"></StackPanel>

                <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock     Text="存储区:" Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0"></TextBlock>
                    <ComboBox    ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding WritePLCModel.Area }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="数据类型:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding WritePLCModel.DataType }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox   Text="{Binding  WritePLCModel.Address }"  Width="100"  Style="{StaticResource  txtTextBoxStyle}"  />
                    <TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding WritePLCModel.Count}"  Width="60"   Style="{StaticResource  txtTextBoxStyle}"  />
                    <Button Content="写入" Height="30" Width="100"   Command="{Binding WriteCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}" />
                </StackPanel>

                <StackPanel Orientation="Vertical" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock   Text="写入数据(多个数据之间用逗号隔开)" Style="{StaticResource  txtTextBlockStyle}"  Margin="0 3 0 9" ></TextBlock>
                    <TextBox    Text="{Binding WriteWords ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"  />
                </StackPanel>

            </Grid>
        </Grid>
    </Grid>
</Window>

 

 8、启动MC服务器

 9、异常错误处理

 

10、操作测试

1、连接PLC

2、读取数据,short,float,bool

 

3、写入数据,short,float

 写入short

写入float

 

3、小结

 

走过路过不要错过,点赞关注收藏又圈粉,共同致富。

欢迎抄袭,复制,分享,转载,学习,截图..............

欢迎抄袭,复制,分享,转载,学习,截图..............

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
以下是一个使用C#编写的基于Modbus TCP协议的上位三菱PLC通信程序的示例: ```csharp using System; using System.Net; using System.Net.Sockets; namespace ModbusTCP { class Program { static void Main(string[] args) { IPAddress ipAddress = IPAddress.Parse("192.168.1.1"); // PLC的IP地址 int port = 502; // Modbus TCP协议的默认端口号 TcpClient client = new TcpClient(); client.Connect(ipAddress, port); NetworkStream stream = client.GetStream(); byte[] txData = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x64, 0x00, 0x02 }; // 读取地址为0x64的2个寄存器的指令 stream.Write(txData, 0, txData.Length); byte[] rxData = new byte[1024]; int bytesRead = stream.Read(rxData, 0, rxData.Length); ushort[] data = new ushort[2]; for (int i = 0; i < 2; i++) { data[i] = (ushort)(rxData[9 + i * 2] << 8 | rxData[10 + i * 2]); } Console.WriteLine("读取到的数据为:" + string.Join(",", data)); stream.Close(); client.Close(); } } } ``` 在上面的示例中,我们使用了TcpClient类来建立与PLC的连接,并通过NetworkStream类发送和接收数据。我们发送了一个读取地址为0x64的2个寄存器的指令,然后从接收到的数据中提取了这两个寄存器的值,并将其打印到控制台上。 当然,实际应用中还需要考虑异常处理、数据类型转换、多个寄存器的读写等情况。但是,这个示例应该可以帮助你了解如何使用C#编写基于Modbus TCP协议的上位三菱PLC通信程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqwest

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值