Hand in hand use WPF MVVM to make USB debugging assistant Demo

1. USB Debugging Assistant Demo

The Demo uses the WPF framework, based on the MVVM design pattern, to implement the USB debugging assistant, and the effect is shown in the figure:

insert image description here
Realized functions: The upper computer (USB debugging assistant) communicates with the lower computer (ZYNQ) to send and receive data through USB.
Experimental environment: Visual Studio 2022
Control library: HandyControl uses handy open source WPF control HandyControl
USB library: LibUsbDotNet
Complete project: Handy use together WPF MVVM makes USB debugging assistant Demo complete project file
Gitee link: https://gitee.com/haileifly/wpf-usb.git

2. Function demonstration

The Demo code structure is shown in the figure, and it is completed by referring to the MVVM design pattern

insert image description here
After the project is running, the interface is as shown in the figure:

insert image description here

The USB device is connected through two IDs. The default ID is randomly input, so if you click directly, it 连接USB设备will pop up that no device is found, as shown in the figure:

insert image description here
After the lower computer is connected normally, you can select the corresponding USB device in the drop-down box, as shown in the figure:

insert image description here
The number of bytes sent and received can also be set, as shown in the figure:

insert image description here
After the setting is complete, just click 连接USB设备it. At this time, you can open the Bus Hound super software bus protocol analyzer to observe the sending and receiving data, as shown in the figure:

insert image description here
After USB发送数据区entering the data, click to start sending, and you can see that the Bus Hound has been sent. As shown in the figure, the reason why the sending data format is so is because the communication protocol header frame, check frame and trailer of the upper computer and the lower computer are customized. frame:

insert image description here

Click 开始接收, the lower computer will return the data to the upper computer interface, and the Bus Hound will display the received data, the two are consistent, as shown in the figure:

insert image description here

Send and receive data again:

insert image description here
Finally, click 断开USB设备, as shown in the figure:

insert image description here

3. UI interface XAML

The UI interface code MainWindow.xaml is as follows:

<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>

Since the open source control library: HandyControl is used, the App.xaml code needs to be written as follows:

<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. Background logic CS

Background MainWindow.xaml.cs code is as follows:

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();
        }
    }
}

The USB parameter initialization class, that is, the interface initialization parameters, the UsbParameter.cs code is as follows:

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 update data class, CurrentParameter.cs code is as follows:

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);
            }
        }
    }
}

Response data real-time update class, NotificationObject.cs code is as follows:

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));
            }
        }
    }
}

Button command class, DelegateCommand.cs code is as follows:

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 code is as follows:

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();
        }
    }
}

Data processing class, including custom communication protocol, DataProcess.cs code is as follows:

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;
        }
    }
}

Global variable class, GlobalVariable.cs code is as follows:

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)的代码,在此表示感谢

I hope this article is helpful to everyone. If there is anything wrong with the above, please correct me.

Sharing determines the height, and learning widens the gap

Guess you like

Origin blog.csdn.net/qq_42078934/article/details/131966988