c#與西門子PLC1500基于sharp7通信學(xué)習(xí)2.利用WPF MVVM 讀寫DB塊

1、利用wpf+mvvm作為上位機(jī)開發(fā)技術(shù),通過讀寫分離的形式,啟動(dòng)一個(gè)線程來進(jìn)行對DB塊數(shù)據(jù)的讀取顯示;通過按鈕事件對選中的字段向PLCDB塊寫入數(shù)據(jù)。


上位機(jī)界面



PLCDB塊


復(fù)制DB塊的文本到EXCEL中作為基礎(chǔ)配置文件供上位機(jī)讀取



項(xiàng)目目錄

2:主要代碼

2.1 View層

<hc:Window x:Class="HandyControlProject1.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:hc="https://handyorg.github.io/handycontrol"

? ? ? ? mc:Ignorable="d"

? ? ? ? DataContext="{Binding Source={StaticResource Locator},Path=Main}"

? ? ? ? Title="MainWindow"

? ? ? ? ? Loaded="Window_Loaded"

? ? ? ? WindowStartupLocation="CenterScreen"

? ? ? ? Style="{StaticResource WindowWin10}"

? ? ? ? ShowTitle="True"

? ? ? ? Height="450"

? ? ? ? Width="800">?

? ? <Grid>

? ? ? ? <Grid.RowDefinitions>

? ? ? ? ? ? <RowDefinition Height="50" />

? ? ? ? ? ? <RowDefinition />

? ? ? ? ? ? <RowDefinition Height="20" />

? ? ? ? </Grid.RowDefinitions>

? ? ? ? <StackPanel Grid.Row="0" Orientation="Horizontal">

? ? ? ? ? ? <Button x:Name="button" Click="button_Click" Content="Connect" HorizontalAlignment="Left" Margin="5" VerticalAlignment="Center" Width="75" />

? ? ? ? ? ? <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="5" TextWrapping="Wrap" Text="192.168.1.140" VerticalAlignment="Center" Width="120"/>

? ? ? ? ? ? <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="5" TextWrapping="Wrap" Text="" VerticalAlignment="Center"/>

? ? ? ? </StackPanel>

? ? ? ? <Grid Grid.Row="1">

? ? ? ? ? ? <Grid.ColumnDefinitions>

? ? ? ? ? ? ? ? <ColumnDefinition Width="5*" />

? ? ? ? ? ? ? ? <ColumnDefinition Width="*" />

? ? ? ? ? ? </Grid.ColumnDefinitions>

? ? ? ? ? ? <DataGrid Grid.Column="0" SelectedItem="{Binding SelectedTag}" ItemsSource="{Binding DB103TagList}" />

? ? ? ? ? ? <Border Grid.Column="1" Background="Gray" BorderBrush="White" BorderThickness="1" CornerRadius="5">

? ? ? ? ? ? ? ? <StackPanel Orientation="Vertical">

? ? ? ? ? ? ? ? ? ? <TextBlock Foreground="Yellow" FontSize="18" Text="{Binding SelectedTag.TagName}"></TextBlock>

? ? ? ? ? ? ? ? ? ? <TextBox Margin="0,5" x:Name="txtTagValue"></TextBox>

? ? ? ? ? ? ? ? ? ? <Button Margin="0,5" x:Name="WriteTagValue" Content="寫入" Click="WriteTagValue_Click"></Button>

? ? ? ? ? ? ? ? </StackPanel>

? ? ? ? ? ? </Border>

? ? ? ? </Grid>? ? ? ?

? ? ? ? <StackPanel Grid.Row="2" Orientation="Horizontal">

? ? ? ? ? ? <TextBlock x:Name="cputime"></TextBlock>

? ? ? ? ? ? <TextBlock x:Name="debugmsg" Margin="10,0"></TextBlock>

? ? ? ? </StackPanel>

? ? </Grid>

</hc:Window>


using System;

using System.Collections.Generic;

using System.IO;

using System.Net;

using System.Runtime.InteropServices;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.Threading;

using System.Threading.Tasks;

using CommonServiceLocator;

using HandyControlProject1.ViewModel;

using Sharp7;

namespace HandyControlProject1

{

? ? public partial class MainWindow

? ? {

? ? ? ? private CancellationTokenSource TokenSource;

? ? ? ? private Task CurrentTask;

? ? ? ? MainViewModel Main;

? ? ? ? S7Client client;

? ? ? ? S7Client.S7CpuInfo s7CpuInfo;

? ? ? ? S7Client.S7OrderCode s7OrderCode;? ?


? ? ? ? public MainWindow()

? ? ? ? {

? ? ? ? ? ? InitializeComponent();

? ? ? ? ? ? Main= ServiceLocator.Current.GetInstance<MainViewModel>();

? ? ? ? ? ? client = new Sharp7.S7Client();

? ? ? ? ? ? s7CpuInfo = new S7Client.S7CpuInfo();

? ? ? ? ? ? s7OrderCode = new S7Client.S7OrderCode();


? ? ? ? ? ? //PDU大小為默認(rèn)為480,1500為960,1200、300為240,400為480,

? ? ? ? ? ? //此處用1500測試設(shè)置960。配置文件中的lenght長度應(yīng)該小于Pdu-18,1500的length最大為942,

? ? ? ? ? ? //如果讀取的長度大于942,可以拆分為多個(gè)包讀取

? ? ? ? ? ? client.PduSizeRequested = 960;//設(shè)置pdu

? ? ? ? ? ? //默認(rèn)為PG連接,設(shè)置為基本連接

? ? ? ? ? ? client.SetConnectionType(3);

? ? ? ? }


? ? ? ? private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)

? ? ? ? {

? ? ? ? }? ? ?

? ? ? ? private void button_Click(object sender, System.Windows.RoutedEventArgs e)

? ? ? ? {

? ? ? ? ? ? if (!client.Connected)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //連接Plc

? ? ? ? ? ? ? ? var result = client.ConnectTo(this.textBox.Text, 0, 0);

? ? ? ? ? ? ? ? if (result == 0)

? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? client.GetCpuInfo(ref s7CpuInfo);

? ? ? ? ? ? ? ? ? ? client.GetOrderCode(ref s7OrderCode);

? ? ? ? ? ? ? ? ? ? this.textBlock.Text = ($"Connected to {this.textBox.Text},CPU類型:{s7CpuInfo.ModuleTypeName},訂貨號:{s7OrderCode.Code}");

? ? ? ? ? ? ? ? ? ? this.button.Content = "斷開連接";

? ? ? ? ? ? ? ? ? ? //啟動(dòng)界面刷新線程

? ? ? ? ? ? ? ? ? ? // create the cancellation token

? ? ? ? ? ? ? ? ? ? TokenSource = new CancellationTokenSource();

? ? ? ? ? ? ? ? ? ? CancellationToken token = TokenSource.Token;

? ? ? ? ? ? ? ? ? ? // create the task

? ? ? ? ? ? ? ? ? ? CurrentTask = Task.Factory.StartNew(() =>

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? while (true)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (token.IsCancellationRequested)

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setmessage("Task cancel detected");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? byte[] buffer = new byte[310];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int res= client.DBRead(3, 0, buffer.Length, buffer);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Console.WriteLine(client.ErrorText(res));

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? foreach (var item in Main.DB103TagList)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? switch (item.TagType)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? case "Int":

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.TagValue = S7.GetIntAt(buffer, (int)item.TagAddress).ToString();

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? case "Bool":

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? string[] address = item.TagAddress.ToString("0.0").Split('.');

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item.TagValue = S7.GetBitAt(buffer, int.Parse(address[0]), int.Parse(address[1])).ToString();

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? default:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setmessage(client.ExecutionTime.ToString());

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? Thread.Sleep(100);

? ? ? ? ? ? ? ? ? ? ? ? }


? ? ? ? ? ? ? ? ? ? }, token);? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? this.textBlock.Text = (client.ErrorText(result));

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? else

? ? ? ? ? ? {

? ? ? ? ? ? ? ? var result = client.Disconnect();

? ? ? ? ? ? ? ? if (result == 0)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? if (CurrentTask != null)

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? if (CurrentTask.Status == TaskStatus.Running) { }

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? TokenSource.Cancel();

? ? ? ? ? ? ? ? ? ? ? ? ? ? setmessage("Task cancel");

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? this.textBlock.Text = ($"Disconnected from {this.textBox.Text}");

? ? ? ? ? ? ? ? ? ? this.button.Content = "連接";

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? this.textBlock.Text = (client.ErrorText(result));

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }? ? ? ?

? ? ? ? }

? ? ? ? void setmessage(string message)

? ? ? ? {

? ? ? ? ? ? this.Dispatcher.Invoke(() =>

? ? ? ? ? ? {

? ? ? ? ? ? ? ? this.debugmsg.Text = message;

? ? ? ? ? ? ? ? this.cputime.Text = DateTime.Now.ToString();

? ? ? ? ? ? });

? ? ? ? }

? ? ? ? private void WriteTagValue_Click(object sender, System.Windows.RoutedEventArgs e)

? ? ? ? {

? ? ? ? ? ? if (Main.SelectedTag != null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? string[] address = Main.SelectedTag.TagAddress.ToString("0.0").Split('.');

? ? ? ? ? ? ? ? int zhengshu = int.Parse(address[0]);

? ? ? ? ? ? ? ? int xiaoshu = int.Parse(address[1]);

? ? ? ? ? ? ? ? int gewei = int.Parse(address[0]) % 10;? ? ? ? ? ? ?

? ? ? ? ? ? ? ? switch (Main.SelectedTag.TagType)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? case "Int":

? ? ? ? ? ? ? ? ? ? ? ? byte[] buff = new byte[2];

? ? ? ? ? ? ? ? ? ? ? ? int res= client.DBRead(3, zhengshu, buff.Length, buff);

? ? ? ? ? ? ? ? ? ? ? ? if (res == 0)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? S7.SetIntAt(buff, 0, short.Parse(this.txtTagValue.Text));

? ? ? ? ? ? ? ? ? ? ? ? ? ? client.DBWrite(3, zhengshu, buff.Length, buff);

? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case "Bool":

? ? ? ? ? ? ? ? ? ? ? ? byte[] buffbit = new byte[1];

? ? ? ? ? ? ? ? ? ? ? ? int resbit = client.DBRead(3, zhengshu, buffbit.Length, buffbit);

? ? ? ? ? ? ? ? ? ? ? ? if (resbit == 0)

? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? S7.SetBitAt(ref buffbit, 0, xiaoshu, this.txtTagValue.Text == "1" ? true : false);

? ? ? ? ? ? ? ? ? ? ? ? ? ? client.DBWrite(3, zhengshu, buffbit.Length, buffbit);

? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? default:

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ?

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

2.2 ViewModel層

using GalaSoft.MvvmLight;

using HandyControlProject1.Model;

using System.Collections.Generic;

using System.Diagnostics;

using System.IO;

namespace HandyControlProject1.ViewModel

{

? ? /// <summary>

? ? /// This class contains properties that the main View can data bind to.

? ? /// <para>

? ? /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.

? ? /// </para>

? ? /// <para>

? ? /// You can also use Blend to data bind with the tool's support.

? ? /// </para>

? ? /// <para>

? ? /// See http://www.galasoft.ch/mvvm

? ? /// </para>

? ? /// </summary>

? ? public class MainViewModel : ViewModelBase

? ? {

? ? ? ? /// <summary>

? ? ? ? /// Initializes a new instance of the MainViewModel class.

? ? ? ? /// </summary>

? ? ? ? public MainViewModel()

? ? ? ? {

? ? ? ? ? ? ////if (IsInDesignMode)

? ? ? ? ? ? ////{

? ? ? ? ? ? ////? ? // Code runs in Blend --> create design time data.

? ? ? ? ? ? ////}

? ? ? ? ? ? ////else

? ? ? ? ? ? ////{

? ? ? ? ? ? ////? ? // Code runs "for real"

? ? ? ? ? ? ////}

? ? ? ? ? ? ///

? ? ? ? ? ? string appStartupPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);

? ? ? ? ? ? string filePath = appStartupPath+@"\DB103.csv";

? ? ? ? ? ? FileStream fileStream = new FileStream(filePath,FileMode.Open,FileAccess.Read);

? ? ? ? ? ? StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.Default);? ? ? ? ?

? ? ? ? ? ? string str = null;

? ? ? ? ? ? DB103TagList = new List<Tags>();

? ? ? ? ? ? while ((str = reader.ReadLine()) != null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Tags tag = new Tags();

? ? ? ? ? ? ? ? string[] strs = str.Split(',');

? ? ? ? ? ? ? ? if (strs.Length == 3)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? tag.TagName = strs[0].ToString();

? ? ? ? ? ? ? ? ? ? tag.TagType = strs[1].ToString();

? ? ? ? ? ? ? ? ? ? tag.TagAddress = double.Parse(strs[2].ToString());

? ? ? ? ? ? ? ? ? ? DB103TagList.Add(tag);

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }

? ? ? ? ? ? reader.Close();

? ? ? ? ? ? fileStream.Close();

? ? ? ? }

? ? ? ? private List<Tags> _DB103TagList;

? ? ? ? public List<Tags> DB103TagList

? ? ? ? {

? ? ? ? ? ? get { return _DB103TagList; }

? ? ? ? ? ? set { _DB103TagList = value;

? ? ? ? ? ? ? ? RaisePropertyChanged();

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? private Tags _SelectedTag;

? ? ? ? public Tags SelectedTag

? ? ? ? {

? ? ? ? ? ? get { return _SelectedTag; }

? ? ? ? ? ? set { _SelectedTag = value;

? ? ? ? ? ? ? ? RaisePropertyChanged();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

2.3 Model

using GalaSoft.MvvmLight;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace HandyControlProject1.Model

{

? ? public class Tags:ObservableObject

? ? {

? ? ? ? private string _TagName;

? ? ? ? public string TagName

? ? ? ? {

? ? ? ? ? ? get { return _TagName; }

? ? ? ? ? ? set { _TagName = value;

? ? ? ? ? ? ? ? RaisePropertyChanged(()=>TagName);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? private string _TagType;

? ? ? ? public string TagType

? ? ? ? {

? ? ? ? ? ? get { return _TagType; }

? ? ? ? ? ? set { _TagType = value;

? ? ? ? ? ? ? ? RaisePropertyChanged(() => TagType);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? private double _TagAddress;

? ? ? ? public double TagAddress

? ? ? ? {

? ? ? ? ? ? get { return _TagAddress; }

? ? ? ? ? ? set { _TagAddress = value;

? ? ? ? ? ? ? ? RaisePropertyChanged(() => TagAddress);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? private string _TagValue;

? ? ? ? public string TagValue

? ? ? ? {

? ? ? ? ? ? get { return _TagValue; }

? ? ? ? ? ? set { _TagValue = value;

? ? ? ? ? ? ? ? RaisePropertyChanged(() => TagValue);

? ? ? ? ? ? }

? ? ? ? }

? ? }

}


3.需要注意的問題

當(dāng)多線程進(jìn)行數(shù)據(jù)讀取和數(shù)據(jù)寫入時(shí),會(huì)出現(xiàn)線程交叉訪問導(dǎo)致數(shù)據(jù)讀寫異常的情況,可以修改sharp7源代碼在DBRead和DBWrite函數(shù)中加鎖處理該問題。

?????????private static object objlock = new object();

? ? ? ? public int DBRead(int DBNumber, int Start, int Size, byte[] Buffer)

? ? ? ? {

? ? ? ? ? ? lock (objlock)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return ReadArea(S7Consts.S7AreaDB, DBNumber, Start, Size, S7Consts.S7WLByte, Buffer);

? ? ? ? ? ? }


? ? ? ? }

? ? ? ? public int DBWrite(int DBNumber, int Start, int Size, byte[] Buffer)

? ? ? ? {

? ? ? ? ? ? lock (objlock)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return WriteArea(S7Consts.S7AreaDB, DBNumber, Start, Size, S7Consts.S7WLByte, Buffer);

? ? ? ? ? ? }

? ? ? ? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容