From c31c5115537a7e55db1a5d39d726e412514e5a80 Mon Sep 17 00:00:00 2001 From: zhangyongpan Date: Fri, 25 Jul 2025 14:37:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=B2=E5=8F=A3=E8=AE=BE=E7=BD=AE=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E5=88=9B=E5=BB=BA=EF=BC=8C=E9=93=BE=E6=8E=A5=E5=92=8C?= =?UTF-8?q?=E6=96=AD=E5=BC=80=E6=8C=87=E4=BB=A4=E6=B7=BB=E5=8A=A0=EF=BC=8C?= =?UTF-8?q?=E4=B8=8B=E6=8B=89=E6=A1=86=E7=BB=91=E5=AE=9A=E6=9E=9A=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ModbusDemo/App.xaml.cs | 22 +++ .../Extension/EnumBindingSourceExtension.cs | 56 ++++++ ModbusDemo/MainWindow.xaml | 9 +- ModbusDemo/ModbusDemo.csproj | 1 + ModbusDemo/Uitls/CRCUitl.cs | 81 +++++++++ ModbusDemo/VIew/SettingsUC.xaml | 152 ++++++++++++++++- ModbusDemo/VIewModel/MainWindowViewModel.cs | 9 +- ModbusDemo/VIewModel/SettingsUCViewModel.cs | 161 +++++++++++++++++- 8 files changed, 478 insertions(+), 13 deletions(-) create mode 100644 ModbusDemo/Extension/EnumBindingSourceExtension.cs create mode 100644 ModbusDemo/Uitls/CRCUitl.cs diff --git a/ModbusDemo/App.xaml.cs b/ModbusDemo/App.xaml.cs index ca522b2..0d3cea4 100644 --- a/ModbusDemo/App.xaml.cs +++ b/ModbusDemo/App.xaml.cs @@ -4,6 +4,8 @@ using Prism.DryIoc; using Prism.Ioc; using System.Configuration; using System.Data; +using System.DirectoryServices; +using System.IO.Ports; using System.Windows; namespace ModbusDemo @@ -35,7 +37,27 @@ namespace ModbusDemo containerRegistry.RegisterForNavigation(); //将寄存器操作页面和寄存器操作页面的VM结合起来 containerRegistry.RegisterForNavigation(); + //将窗口注册为全局唯一的单例 + containerRegistry.RegisterSingleton(); } + /// + /// 程序打开默认是设置界面,来设置串口的各个东西 + /// + protected override void OnInitialized() + { + MainWindowViewModel mainWindowViewModel = App.Current.MainWindow.DataContext as MainWindowViewModel; + mainWindowViewModel!.DefultNaigation(); + base.OnInitialized(); + } + + + + //private SerialPort CreateSerialPort() + //{ + // SerialPort serialPort = new SerialPort(); + + // return serialPort; + //} } } diff --git a/ModbusDemo/Extension/EnumBindingSourceExtension.cs b/ModbusDemo/Extension/EnumBindingSourceExtension.cs new file mode 100644 index 0000000..027db05 --- /dev/null +++ b/ModbusDemo/Extension/EnumBindingSourceExtension.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Markup; + +namespace ModbusDemo.Extension +{ + class EnumBindingSourceExtension : MarkupExtension + { + private Type _enumType; + + public Type EnumType + { + get => _enumType; + set + { + if (value != _enumType) + { + if (value != null) + { + Type enumType = Nullable.GetUnderlyingType(value) ?? value; + if (!enumType.IsEnum) + throw new ArgumentException("Type must be for an Enum."); + } + + _enumType = value; + } + } + } + + public EnumBindingSourceExtension() { } + + public EnumBindingSourceExtension(Type enumType) + { + EnumType = enumType; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + if (_enumType == null) + throw new InvalidOperationException("The EnumType must be specified."); + + var actualEnumType = Nullable.GetUnderlyingType(_enumType) ?? _enumType; + var enumValues = Enum.GetValues(actualEnumType); + + if (actualEnumType == _enumType) + return enumValues; + + var tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1); + enumValues.CopyTo(tempArray, 1); + return tempArray; + } + } +} diff --git a/ModbusDemo/MainWindow.xaml b/ModbusDemo/MainWindow.xaml index 4e03130..e3fd029 100644 --- a/ModbusDemo/MainWindow.xaml +++ b/ModbusDemo/MainWindow.xaml @@ -11,8 +11,9 @@ xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel,IsDesignTimeCreatable=True}" Title="MainWindow" - Width="1000" + Width="900" Height="600" + WindowStartupLocation="CenterScreen" mc:Ignorable="d"> @@ -36,10 +37,10 @@ - - + + - + diff --git a/ModbusDemo/ModbusDemo.csproj b/ModbusDemo/ModbusDemo.csproj index fb832b1..ddcf4d4 100644 --- a/ModbusDemo/ModbusDemo.csproj +++ b/ModbusDemo/ModbusDemo.csproj @@ -11,6 +11,7 @@ + diff --git a/ModbusDemo/Uitls/CRCUitl.cs b/ModbusDemo/Uitls/CRCUitl.cs new file mode 100644 index 0000000..c28d880 --- /dev/null +++ b/ModbusDemo/Uitls/CRCUitl.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ModbusDemo.Uitls +{ + public static class CRCUitl + { + + private static readonly byte[] aucCRCHi = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40 + }; + private static readonly byte[] aucCRCLo = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, + 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, + 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, + 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, + 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, + 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, + 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, + 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, + 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, + 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, + 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, + 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, + 0x41, 0x81, 0x80, 0x40 + }; + + /// + /// CRC校验 + /// + /// 字节数组 + /// 验证长度 + /// 2个字节 + public static byte[] CalculateCRC(byte[] pucFrame, int usLen) + { + int i = 0; + byte[] res = new byte[2] { 0xFF, 0xFF }; + ushort iIndex; + while (usLen-- > 0) + { + iIndex = (ushort)(res[0] ^ pucFrame[i++]); + res[0] = (byte)(res[1] ^ aucCRCHi[iIndex]); + res[1] = aucCRCLo[iIndex]; + } + return res; + } + } +} diff --git a/ModbusDemo/VIew/SettingsUC.xaml b/ModbusDemo/VIew/SettingsUC.xaml index 89510e3..8c7e3b3 100644 --- a/ModbusDemo/VIew/SettingsUC.xaml +++ b/ModbusDemo/VIew/SettingsUC.xaml @@ -5,13 +5,153 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ModbusDemo.VIew" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:EnumEx="clr-namespace:ModbusDemo.Extension" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + xmlns:ports="clr-namespace:System.IO.Ports;assembly=System" + xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" + d:DataContext="{d:DesignInstance Type=viewmodel:SettingsUCViewModel, + IsDesignTimeCreatable=True}" d:DesignHeight="450" d:DesignWidth="800" + d:Background="White" mc:Ignorable="d"> - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModbusDemo/VIewModel/MainWindowViewModel.cs b/ModbusDemo/VIewModel/MainWindowViewModel.cs index 424dabf..15849c6 100644 --- a/ModbusDemo/VIewModel/MainWindowViewModel.cs +++ b/ModbusDemo/VIewModel/MainWindowViewModel.cs @@ -50,7 +50,9 @@ namespace ModbusDemo.VIewModel { _regionManager.Regions["ModbusRegion"].RequestNavigate(info.ViewName); } - + /// + /// 初始化左下拉框 + /// private void CreateLeftMenus() { LeftMenusList = new(); @@ -58,5 +60,10 @@ namespace ModbusDemo.VIewModel LeftMenusList.Add(new MenusInfo() { Icon = "BlurCircular", MenuName = "寄存器操作", ViewName = "RegisterUC" }); LeftMenusList.Add(new MenusInfo() { Icon = "Settings", MenuName = "串口设置", ViewName = "SettingsUC" }); } + + public void DefultNaigation() + { + _regionManager.Regions["ModbusRegion"].RequestNavigate("SettingsUC"); + } } } diff --git a/ModbusDemo/VIewModel/SettingsUCViewModel.cs b/ModbusDemo/VIewModel/SettingsUCViewModel.cs index 0b4f54e..2f81bfd 100644 --- a/ModbusDemo/VIewModel/SettingsUCViewModel.cs +++ b/ModbusDemo/VIewModel/SettingsUCViewModel.cs @@ -1,13 +1,170 @@ -using Prism.Mvvm; +using ModbusDemo.Uitls; +using Prism.Commands; +using Prism.Mvvm; using System; using System.Collections.Generic; +using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ModbusDemo.VIewModel { - class SettingsUCViewModel:BindableBase + + class SettingsUCViewModel : BindableBase { + public DelegateCommand DisConnectionCmm { get; set; } + //链接窗口的命令 + public DelegateCommand ConnectionCmm { get; set; } + + //获取串口 + private SerialPort _serialPort; + //设置串口名字 + private string _portName = "COM1"; + + public string PortName + { + get { return _portName; } + set + { + _portName = value; + RaisePropertyChanged(); + } + } + + //设置波特率 + private string _baudRate = "19200"; + + public string BaudRate + { + get { return _baudRate; } + set + { + _baudRate = value; + RaisePropertyChanged(); + } + } + + //设置数据位 + private string _dataBits = "8"; + + public string DataBits + { + get { return _dataBits; } + set + { + _dataBits = value; + + RaisePropertyChanged(); + } + } + //设置校验位 + private Parity _parity = Parity.Even; + + public Parity Parity + { + get { return _parity; } + set + { + _parity = value; + RaisePropertyChanged(); + } + } + + //设置停止位 + private StopBits _stopBits = StopBits.One; + + public StopBits StopBits + { + get { return _stopBits; } + set + { + _stopBits = value; + RaisePropertyChanged(); + } + } + + public SettingsUCViewModel() + { + + } + /// + /// 从容器中获取创建的窗口 + /// + /// + public SettingsUCViewModel(SerialPort serialPort) + { + _serialPort = serialPort; + ConnectionCmm = new DelegateCommand(Connection); + DisConnectionCmm = new DelegateCommand(DisConnection); + } + + private void DisConnection() + { + if (_serialPort.IsOpen) + { + _serialPort.Close(); + } + } + + /// + /// 串口参数设置 + /// + private void Connection() + { + //todo,做数据的判空处理 + if (!_serialPort.IsOpen) + { + _serialPort.PortName = GetComboBoxItemValue(this.PortName); + _serialPort.BaudRate = int.Parse(GetComboBoxItemValue(this.BaudRate)); + _serialPort.Parity = this.Parity; + _serialPort.StopBits = this.StopBits; + _serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); + _serialPort.Open(); + } + + + + + + List bytes = new List(); + bytes.Add(0x01); + bytes.Add(0x05); + + + bytes.Add(BitConverter.GetBytes(301)[1]); + bytes.Add(BitConverter.GetBytes(301)[0]); + + + bytes.Add(0xFF); + bytes.Add(0x00); + + byte[] bytes1 = CRCUitl.CalculateCRC(bytes.ToArray(), bytes.Count); + + bytes.Add(bytes1[0]); + bytes.Add(bytes1[1]); + byte[] bytes2 = bytes.ToArray(); + System.Threading.Thread.Sleep(200); // 等待200毫秒 + + byte[] response = new byte[_serialPort.BytesToRead]; + //int bytesRead = serialPort.Read(response, 0, response.Length); + + //string hexResponse = BitConverter.ToString(response, 0, bytesRead); + _serialPort.Write(bytes2, 0, bytes2.Length); + } + /// + /// 处理下拉框的选择信息 + /// + /// + /// + private string GetComboBoxItemValue(string ComboBoxItem) + { + + string displayText = ComboBoxItem.ToString(); + string cleanText = displayText.Replace("System.Windows.Controls.ComboBoxItem: ", ""); + return cleanText; + } + + } }