WPF MVVM を連携して使用して USB デバッグ アシスタントのデモを作成する

1.USBデバッグアシスタントのデモ

このデモでは、MVVM 設計パターンに基づいた WPF フレームワークを使用して USB デバッグ アシスタントを実装します。その効果を図に示します。

ここに画像の説明を挿入
実現機能:上位コンピュータ(USBデバッグアシスタント)が下位コンピュータ(ZYNQ)と通信し、USB経由でデータの送受信を行う 実験環境:
Visual Studio 2022
コントロールライブラリ:HandyControlは便利なオープンソースのWPFコントロールを使用 HandyControl
USBライブラリ:LibUsbDotNet
プロジェクト完了:一緒に便利に使用 WPF MVVM は USB デバッグ アシスタントを作成します デモの完全なプロジェクト ファイル
Gitee リンク: https://gitee.com/haileifly/wpf-usb.git

2. 機能デモ

デモ コードの構造は図に示されており、MVVM 設計パターンを参照することで完成します。

ここに画像の説明を挿入
プロジェクトが実行されると、インターフェイスは次の図のようになります。

ここに画像の説明を挿入

USB デバイスは 2 つの ID を介して接続されています。デフォルトの ID はランダムに入力されるため、直接クリックすると、连接USB设备図に示すように、デバイスが見つからないというポップアップが表示されます。

ここに画像の説明を挿入
下のコンピュータが正常に接続されたら、図に示すように、ドロップダウン ボックスで対応する USB デバイスを選択できます。

ここに画像の説明を挿入
図に示すように、送受信されるバイト数も設定できます。

ここに画像の説明を挿入
設定が完了したら、クリックするだけで连接USB设备、図に示すように、Bus Hound スーパー ソフトウェア バス プロトコル アナライザーを開いて、送受信データを観察できます。

ここに画像の説明を挿入
データ入力後USB发送数据区、クリックして送信を開始すると、バスハウンドが送信されたことがわかります 図のように、送信データ形式がこのようになるのは、通信プロトコルのヘッダフレーム、チェックフレーム、トレーラが構成されているためです。上部のコンピューターと下部のコンピューターはカスタマイズされています。フレーム:

ここに画像の説明を挿入

をクリックする开始接收と、下のコンピュータが上のコンピュータ インターフェイスにデータを返し、Bus Hound が受信したデータを表示します。図に示すように、この 2 つは一致しています。

ここに画像の説明を挿入

データを再度送受信します。

ここに画像の説明を挿入
最後に、断开USB设备図に示すように、 をクリックします。

ここに画像の説明を挿入

3. UIインターフェイスXAML

UI インターフェイス コード MainWindow.xaml は次のとおりです。

<Window
        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:Wpf_USB"
        xmlns:hc="https://handyorg.github.io/handycontrol" x:Class="Wpf_USB.MainWindow"
        mc:Ignorable="d"
        Title="WPF_USB" Height="480" Width="800" ResizeMode="CanMinimize">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="160*"/>
            <ColumnDefinition Width="160*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="60*"/>
            <RowDefinition Height="60*"/>
        </Grid.RowDefinitions>
        <GroupBox Header="USB设备信息" BorderBrush="Black" FontSize="20" FontWeight="Bold" Margin="5,5,5,5" Grid.RowSpan="2">
            <StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock TextWrapping="Wrap" Text="VendorID:" Width="auto"  RenderTransformOrigin="0.478,1.336" Padding="0,10,0,0" Height="44" Margin="10"/>
                    <ComboBox Width="177" Margin="15,10,5,10" ItemsSource="{Binding UsbPar.VendorID}" SelectedItem="{Binding CuPar.VendorID}" IsEnabled="{Binding CuPar.EnableSelect}"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock TextWrapping="Wrap" Text="ProductID:" Width="auto" RenderTransformOrigin="0.478,1.336" Padding="0,10,0,0" Height="44" Margin="10"/>
                    <ComboBox Width="177" Margin="10,10,5,10" ItemsSource="{Binding UsbPar.ProductID}" SelectedItem="{Binding CuPar.ProductID}" IsEnabled="{Binding CuPar.EnableSelect}"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <Button Content="连接USB设备" Margin="20,0,10,0" FontSize="16" Height="38" Command="{Binding OpenUsbDev}"/>
                    <Button Content="断开USB设备" Margin="20,0,10,0" FontSize="16" Height="38" Command="{Binding CloseUsbDev}"/>
                </StackPanel>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="USB接收数据区" FontSize="20"  FontWeight="Bold" BorderBrush="#FF7ED866" Margin="5,5,5,5" Grid.Row="2" Grid.RowSpan="2">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <TextBox Name="ReceiveData" TextWrapping="Wrap" Text="{Binding CuPar.ReadDataString}" FontWeight="Normal" FontSize="16"/>
            </ScrollViewer>
        </GroupBox>
        <GroupBox Header="接收数据设置" FontSize="20"  FontWeight="Bold" Margin="5,5,5,5" BorderBrush="#FF5570C7" Grid.Column="1">
            <StackPanel Orientation="Horizontal">
                <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="BytesRead:" Padding="0,15,0,0"/>
                <ComboBox Width="130" Height="40" ItemsSource="{Binding UsbPar.BytesRead}" SelectedItem="{Binding CuPar.BytesRead}" IsEnabled="{Binding CuPar.EnableSelect}"/>
                <Button Content="开始接收" FontSize="20" Height="58" Margin="5" Command="{Binding UsbDevRead}"/>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="发送数据设置" FontSize="20"  FontWeight="Bold" Margin="5,5,5,5"  BorderBrush="#FF5D29A0" Grid.Column="1" Grid.Row="1">
            <StackPanel Orientation="Horizontal">
                <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="BytesWrite:" Padding="0,15,0,0"/>
                <ComboBox Width="130" Height="40" ItemsSource="{Binding UsbPar.BytesWrite}" SelectedItem="{Binding CuPar.BytesWrite}" IsEnabled="{Binding CuPar.EnableSelect}"/>
                <Button Content="开始发送" FontSize="20" Height="58" Margin="5" Command="{Binding UsbDevWrite}"/>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="USB发送数据区" FontSize="20"  FontWeight="Bold" Margin="5,5,5,5" BorderBrush="#FFA42D84" Grid.Column="1" Grid.RowSpan="2" Grid.Row="2">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <TextBox Name="SendData" TextWrapping="Wrap" Text="{Binding CuPar.WriteData}" FontWeight="Normal" FontSize="16"/>
            </ScrollViewer>
        </GroupBox>
    </Grid>
</Window>

オープンソースのコントロールライブラリHandyControlを使用するため、App.xamlのコードは次のように記述する必要があります。

<Application x:Class="Wpf_USB.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Wpf_USB"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

4. バックグラウンドロジックCS

バックグラウンドの MainWindow.xaml.cs コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Wpf_USB.ViewModels;

namespace Wpf_USB
{
    
    
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
    
    
        public MainWindow()
        {
    
    
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }
}

USB パラメータ初期化クラス、つまりインターフェイス初期化パラメータの UsbParameter.cs コードは次のとおりです。

using LibUsbDotNet.Main;
using LibUsbDotNet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Wpf_USB.ViewModels
{
    
    
    class UsbParameter : NotificationObject
    {
    
    
        private ObservableCollection<int> vendorid = new ObservableCollection<int>() {
    
     1234 };
        public ObservableCollection<int> VendorID 
        {
    
    
            get {
    
     return vendorid; }
            set
            {
    
    
                vendorid = value;
                this.RaisePropertyChanged("VendorID");
            }
        }

        private ObservableCollection<int> productid = new ObservableCollection<int>() {
    
     1 };
        public ObservableCollection<int> ProductID
        {
    
    
            get {
    
     return productid; }
            set
            {
    
    
                productid = value;
                this.RaisePropertyChanged("ProductID");
            }
        }

        private ObservableCollection<int> bytesread = new ObservableCollection<int>() {
    
     512, 1024, 2048, 4096, 8192, 16384 };
        public ObservableCollection<int> BytesRead
        {
    
    
            get {
    
     return bytesread; }
            set
            {
    
    
                bytesread = value;
                this.RaisePropertyChanged("BytesRead");
            }
        }

        private ObservableCollection<int> byteswrite = new ObservableCollection<int>() {
    
     512, 1024, 2048, 4096, 8192, 16384 };
        public ObservableCollection<int> BytesWrite
        {
    
    
            get {
    
     return byteswrite; }
            set
            {
    
    
                byteswrite = value;
                this.RaisePropertyChanged("BytesWrite");
            }
        }
        public void UsbDeviceFind()
        {
    
    
            UsbRegDeviceList allDevices = UsbDevice.AllDevices;
            if (allDevices != null)
            {
    
    
                foreach (UsbRegistry usbRegistry in allDevices)
                {
    
    
                    VendorID.Add(usbRegistry.Vid);
                    ProductID.Add(usbRegistry.Pid);
                }
                UsbDevice.Exit();
            }
            else {
    
     MessageBox.Show("UsbDevive Not Found."); }            
        }
    }
}

USB 更新データ クラス、CurrentParameter.cs コードは次のとおりです。

using LibUsbDotNet;
using LibUsbDotNet.Main;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows;
using System.Runtime.Remoting.Messaging;
using System.Collections.ObjectModel;
using System.Reflection;
using Wpf_USB.Models;

namespace Wpf_USB.ViewModels
{
    
    
    class CurrentParameter : NotificationObject
    {
    
    
        public CurrentParameter()
        {
    
    
            GloVar = new GlobalVariable();
            DataPro = new DataProcess();
        }
        private GlobalVariable gloVar;
        public GlobalVariable GloVar
        {
    
    
            get {
    
     return gloVar; }
            set
            {
    
    
                gloVar = value;
            }
        }
        private DataProcess dataPro;
        public DataProcess DataPro
        {
    
    
            get {
    
     return dataPro; }
            set
            {
    
    
                dataPro = value;
            }
        }
        private int vendorid;
        public int VendorID
        {
    
    
            get {
    
     return vendorid; }
            set
            {
    
    
                vendorid = value;
                this.RaisePropertyChanged("VendorID");
            }
        }

        private int productid;
        public int ProductID
        {
    
    
            get {
    
     return productid; }
            set
            {
    
    
                productid = value;
                this.RaisePropertyChanged("ProductID");
            }
        }

        private int bytesread;
        public int BytesRead
        {
    
    
            get {
    
     return bytesread; }
            set
            {
    
    
                bytesread = value;
                this.RaisePropertyChanged("BytesRead");
            }
        }

        private int byteswrite;
        public int BytesWrite
        {
    
    
            get {
    
     return byteswrite; }
            set
            {
    
    
                byteswrite = value;
                this.RaisePropertyChanged("BytesWrite");
            }
        }
        private UsbDevice usbDevice;
        private UsbEndpointReader epReader;
        private UsbEndpointWriter epWriter;
        public UsbDevice UsbDevice
        {
    
    
            get {
    
     return usbDevice; }
            set {
    
     usbDevice = value; this.RaisePropertyChanged("UsbDevice"); }
        }
        private byte[] readData;
        private string writeData;
        private string readDataString;
        private bool isOpen;
        private bool enableSelect = true;
        public bool EnableSelect
        {
    
    
            get {
    
     return enableSelect; }
            set {
    
     enableSelect = value; this.RaisePropertyChanged("EnableSelect"); }
        }
        public byte[] ReadData
        {
    
    
            get {
    
     return readData; }
            set {
    
     readData = value; this.RaisePropertyChanged("ReadData"); }
        }
        public string ReadDataString
        {
    
    
            get {
    
     return readDataString; }
            set {
    
     readDataString = value; this.RaisePropertyChanged("ReadDataString"); }
        }
        public string WriteData
        {
    
    
            get {
    
     return writeData; }
            set {
    
     writeData = value; this.RaisePropertyChanged("WriteData"); }
        }

        public bool IsOpen
        {
    
    
            get {
    
     return isOpen; }
            set {
    
     isOpen = value; this.RaisePropertyChanged("IsOpen"); }
        }

        public bool UsbDevicesOpen()
        {
    
    
            if (usbDevice != null && usbDevice.IsOpen)
            {
    
    
                return UsbDevicesClose();
            }
            try
            {
    
    
                UsbDeviceFinder UsbFinder = new UsbDeviceFinder(this.VendorID, this.ProductID);
                usbDevice = UsbDevice.OpenUsbDevice(UsbFinder);
                if (usbDevice == null) throw new Exception("Device Not Found.");
                IUsbDevice wholeUsbDevice = usbDevice as IUsbDevice;
                if (!ReferenceEquals(wholeUsbDevice, null))
                {
    
    
                    wholeUsbDevice.SetConfiguration(1);
                    wholeUsbDevice.ClaimInterface(0);
                }
                epReader = usbDevice.OpenEndpointReader(ReadEndpointID.Ep01);
                epWriter = usbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
                EnableSelect = false;
                if (usbDevice.IsOpen)
                {
    
    
                    return IsOpen = true;
                }
                else
                {
    
    
                    return IsOpen = false;
                }
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show(ex.Message);
            }
            return IsOpen = false;
        }
        public bool UsbDevicesClose()
        {
    
    
            try
            {
    
    
                EnableSelect = true;
                if (usbDevice == null) throw new Exception("Device Not Found.");
                else
                {
    
    
                    if (usbDevice.IsOpen)
                    {
    
    
                        IUsbDevice wholeUsbDevice = usbDevice as IUsbDevice;
                        if (!ReferenceEquals(wholeUsbDevice, null))
                        {
    
    
                            // Release interface #0.
                            wholeUsbDevice.ReleaseInterface(0);
                        }
                        usbDevice.Close();
                        return IsOpen = false;
                    }
                    usbDevice = null;
                    UsbDevice.Exit();
                    return IsOpen = false;
                }
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show(ex.Message);
                return IsOpen = false;
            }
        }
        public void UsbDevicesRead()
        {
    
    
            try 
            {
    
    
                if (usbDevice == null) throw new Exception("Device Not Found.");
                else
                {
    
    
                    int bytesReadCount = BytesRead;
                    readData = new byte[bytesReadCount];
                    ErrorCode ec = epReader.Read(ReadData, 2000, out bytesReadCount);
                    this.DataPro.ReadDataCRC(ReadData);
                    ReadDataString += GloVar.CMD_H.ToString("X2") + " ";
                    ReadDataString += GloVar.CMD_L.ToString("X2") + " ";
                    ReadDataString += GloVar.RESULT_F.ToString("X2") + " ";
                    for (int i = 0; i < GloVar.ReadValidData.Length; i++)
                        ReadDataString += GloVar.ReadValidData[i].ToString("X2") + " ";
                    if (bytesReadCount == 0) MessageBox.Show("No More Bytes.");
                }
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show(ex.Message);
            }
        }
        public void UsbDevicesWrite()
        {
    
    
            try 
            {
    
    
                if (usbDevice == null) throw new Exception("Device Not Found.");
                else
                {
    
    
                    if (!String.IsNullOrEmpty(WriteData))
                    {
    
    
                        int bytesWriteCount = BytesWrite;
                        DataPro.WriteDataCRC(WriteData);
                        ErrorCode ec = epWriter.Write(GloVar.WriteValidData, 2000, out bytesWriteCount);
                        if (ec != ErrorCode.None) MessageBox.Show("Write Fail.");
                    }
                    else
                    {
    
    
                        MessageBox.Show("WriteData Is Empty.");
                    }
                }
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show(ex.Message);
            }
        }
    }
}

応答データのリアルタイム更新クラス、NotificationObject.cs コードは次のとおりです。

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

namespace Wpf_USB.ViewModels
{
    
    
    class NotificationObject : INotifyPropertyChanged
    {
    
    
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
    
    
            if (this.PropertyChanged != null)
            {
    
    
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

ボタン コマンド クラス、DelegateCommand.cs コードは次のとおりです。

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

namespace Wpf_USB.ViewModels
{
    
    
    class DelegateCommand : ICommand
    {
    
    
        public bool CanExecute(object parameter)
        {
    
    
            if (CanExecuteFunc == null)
                return true;
            return this.CanExecuteFunc(parameter);
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
    
    
            if (ExecuteAction == null)
            {
    
    
                return;
            }
            this.ExecuteAction(parameter);
        }

        public Action<object> ExecuteAction {
    
     get; set; }
        public Func<object, bool> CanExecuteFunc {
    
     get; set; }
    }
}

MainWindowViewModel.cs コードは次のとおりです。

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

namespace Wpf_USB.ViewModels
{
    
    
    class MainWindowViewModel : NotificationObject
    {
    
    
        public MainWindowViewModel()
        {
    
    
            UsbPar = new UsbParameter();
            CuPar = new CurrentParameter();
            this.UsbPar.UsbDeviceFind();
            CuPar.VendorID = UsbPar.VendorID[0];
            CuPar.ProductID = UsbPar.ProductID[0];
            CuPar.BytesRead = UsbPar.BytesRead[3];
            CuPar.BytesWrite = UsbPar.BytesWrite[3];
            

            this.OpenUsbDev = new DelegateCommand();
            this.OpenUsbDev.ExecuteAction = new Action<object>(this.OpenUsb);
            this.CloseUsbDev = new DelegateCommand();
            this.CloseUsbDev.ExecuteAction = new Action<object>(this.CloseUsb);
            this.UsbDevRead = new DelegateCommand();
            this.UsbDevRead.ExecuteAction = new Action<object>(this.UsbRead);
            this.UsbDevWrite = new DelegateCommand();
            this.UsbDevWrite.ExecuteAction = new Action<object>(this.UsbWrite);
        }

        private UsbParameter usbPar;
        public UsbParameter UsbPar
        {
    
    
            get {
    
     return usbPar; }
            set
            {
    
    
                usbPar = value;
                this.RaisePropertyChanged("UsbPar");
            }
        }
        private CurrentParameter cuPar;
        public CurrentParameter CuPar
        {
    
    
            get {
    
     return cuPar; }
            set
            {
    
    
                cuPar = value;
                this.RaisePropertyChanged("CuPar");
            }
        }
        public DelegateCommand OpenUsbDev {
    
     get; set; }
        private void OpenUsb(object parameter)
        {
    
    
            this.CuPar.UsbDevicesOpen();
        }
        public DelegateCommand CloseUsbDev {
    
     get; set; }
        private void CloseUsb(object parameter)
        {
    
    
            this.CuPar.UsbDevicesClose();
        }
        public DelegateCommand UsbDevRead {
    
     get; set; }
        private void UsbRead(object parameter)
        {
    
     
            this.CuPar.UsbDevicesRead(); 
        }
        public DelegateCommand UsbDevWrite {
    
     get; set; }
        private void UsbWrite(object parameter)
        {
    
     
            this.CuPar.UsbDevicesWrite();
        }
    }
}

カスタム通信プロトコルを含むデータ処理クラス、DataProcess.cs コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Wpf_USB.ViewModels;

namespace Wpf_USB.Models
{
    
    
    class DataProcess : NotificationObject
    {
    
    
        public DataProcess() 
        {
    
    
            GloVar = new GlobalVariable();
        }

        private GlobalVariable gloVar;
        public GlobalVariable GloVar
        {
    
    
            get {
    
     return gloVar; }
            set
            {
    
    
                gloVar = value;
                this.RaisePropertyChanged("GloVar");
            }
        }

        public void ReadDataCRC(byte[] ReadData)
        {
    
    
            int CheckoutSum = 0;
            int DataLength = ReadData[2] * 256 + ReadData[3];
            if (ReadData[0].ToString("X") != "7E" || ReadData[1].ToString("X") != "7E")
            {
    
    
                GloVar.FrameData_F = true;
                MessageBox.Show("Data Frame Header Error.");
            }
            for (int i=0; i< DataLength; i++)
            {
    
    
                CheckoutSum += ReadData[i + 4];
            }
            if (Convert.ToByte(CheckoutSum & 0xFF) != Convert.ToByte(ReadData[DataLength+4]))
            {
    
    
                GloVar.FrameData_F = true;
                MessageBox.Show("Data Frame Check Error.");
            }
            GloVar.CMD_H = ReadData[4];
            GloVar.CMD_L = ReadData[5];
            GloVar.RESULT_F = ReadData[6];
            GloVar.ReadValidData = new byte[DataLength-3];
            for (int i = 0; i < (DataLength-3); i++)
            {
    
    
                GloVar.ReadValidData[i] = ReadData[i+7];
            }
            if (ReadData[DataLength + 5].ToString("X") != "45" || ReadData[DataLength + 6].ToString("X") != "4E" || ReadData[DataLength + 7].ToString("X") != "44")
            {
    
    
                GloVar.FrameData_F = true;
                MessageBox.Show("Data Frame End Error.");
            }
        }

        public void WriteDataCRC(string WriteData)
        {
    
    
            int CheckoutSum = 0 ;
            string WriteDataHex = WriteData.Replace(" ", "");
            WriteDataHex += WriteDataHex.Length % 2 != 0 ? "0" : "";
            int WriteValidDataLength = WriteDataHex.Length / 2;
            GloVar.WriteValidData = new byte[WriteValidDataLength+8];
            GloVar.WriteValidData[0] = 0x7E;
            GloVar.WriteValidData[1] = 0x7E;
            GloVar.WriteValidData[2] = Convert.ToByte((WriteValidDataLength >> 8) & 0xFF);
            GloVar.WriteValidData[3] = Convert.ToByte(WriteValidDataLength & 0xFF);
            for (int i=0; i<WriteValidDataLength; i++)
            {
    
    
                GloVar.WriteValidData[4+i] = Convert.ToByte(WriteDataHex.Substring(i * 2, 2), 16);
                CheckoutSum += GloVar.WriteValidData[4+i];
            }
            GloVar.WriteValidData[4 + WriteValidDataLength] = Convert.ToByte(CheckoutSum & 0xFF);
            GloVar.WriteValidData[5 + WriteValidDataLength] = 0x45;
            GloVar.WriteValidData[6 + WriteValidDataLength] = 0x4E;
            GloVar.WriteValidData[7 + WriteValidDataLength] = 0x44;
        }
    }
}

グローバル変数クラス、GlobalVariable.cs コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wpf_USB.ViewModels;

namespace Wpf_USB.Models
{
    
    
    class GlobalVariable : NotificationObject
    {
    
    
        private string globalSystemVersion = "1.0.0";
        public string GlobalSystemVersion
        {
    
    
            get {
    
     return globalSystemVersion; }
            set
            {
    
    
                globalSystemVersion = value;
                this.RaisePropertyChanged("GlobalSystemVersion");
            }
        }
        private string globalUpdateTime = "2023.7.27";
        public string GlobalUpdateTime
        {
    
    
            get {
    
     return globalUpdateTime; }
            set
            {
    
    
                globalUpdateTime = value;
                this.RaisePropertyChanged("GlobalUpdateTime");
            }
        }
        private static int cMD_H;
        public int CMD_H
        {
    
    
            get {
    
     return cMD_H; }
            set
            {
    
    
                cMD_H = value;
                this.RaisePropertyChanged("CMD_H");
            }
        }
        private static int cMD_L;
        public int CMD_L
        {
    
    
            get {
    
     return cMD_L; }
            set
            {
    
    
                cMD_L = value;
                this.RaisePropertyChanged("CMD_L");
            }
        }
        private static int rESULT_F;
        public int RESULT_F
        {
    
    
            get {
    
     return rESULT_F; }
            set
            {
    
    
                rESULT_F = value;
                this.RaisePropertyChanged("RESULT_F");
            }
        }
        public static byte[] readValidData;
        public byte[] ReadValidData
        {
    
    
            get {
    
     return readValidData; }
            set
            {
    
    
                readValidData = value;
                this.RaisePropertyChanged("ReadValidData");
            }
        }
        public static byte[] writeValidData;
        public byte[] WriteValidData
        {
    
    
            get {
    
     return writeValidData; }
            set
            {
    
    
                writeValidData = value;
                this.RaisePropertyChanged("WriteValidData");
            }
        }
        public static bool frameData_F = false;
        public bool FrameData_F
        {
    
    
            get {
    
     return frameData_F; }
            set
            {
    
    
                frameData_F = value;
                this.RaisePropertyChanged("FrameData_F");
            }
        }
    }
}

该Demo实现过程中,参考了一些大佬(CSDN和Github)的代码,在此表示感谢

この記事が皆様のお役に立てば幸いです。上記に何か間違っている点がございましたら、ご指摘ください。

共有が高さを決定し、学習が格差を広げる

おすすめ

転載: blog.csdn.net/qq_42078934/article/details/131966988