@@ -13,5 +13,7 @@ namespace ModbusDemo.Device | |||
public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data); | |||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints); | |||
} | |||
} |
@@ -58,7 +58,7 @@ namespace ModbusDemo.Device | |||
Thread.Sleep(300); | |||
byte[] response = new byte[_serialPort.BytesToRead]; | |||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||
return Parseresponse(response,numberOfPoints); | |||
return ParseCoilresponse(response,numberOfPoints); | |||
} | |||
@@ -66,7 +66,7 @@ namespace ModbusDemo.Device | |||
} | |||
public bool[] Parseresponse(byte[] response, ushort numberOfPoints) | |||
public bool[] ParseCoilresponse(byte[] response, ushort numberOfPoints) | |||
{ | |||
//判断发送回来的数据是否正确 | |||
CheckData.CheckResponse(response); | |||
@@ -107,7 +107,12 @@ namespace ModbusDemo.Device | |||
} | |||
return ultimately; | |||
} | |||
/// <summary> | |||
/// 写入多个线圈操作 | |||
/// </summary> | |||
/// <param name="slaveAddress">从站地址</param> | |||
/// <param name="startAddress">起始地址</param> | |||
/// <param name="data">写入的数据</param> | |||
public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data) | |||
{ | |||
List<byte> sendByteList = new List<byte>(); | |||
@@ -172,5 +177,66 @@ namespace ModbusDemo.Device | |||
} | |||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | |||
{ | |||
if (!_serialPort.IsOpen) | |||
{ | |||
MessageBox.Show("串口没有链接,请先链接"); | |||
return null; | |||
} | |||
List<byte> sendByteList = new List<byte>(); | |||
//设置从站地址 | |||
sendByteList.Add(slaveAddress); | |||
//设置功能码 | |||
sendByteList.Add(0x03); | |||
//设置起始地址的高位和低位 | |||
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]); | |||
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]); | |||
//设置读取几个线圈的高位和低位 | |||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[1]); | |||
sendByteList.Add(BitConverter.GetBytes(numberOfPoints)[0]); | |||
//获取CRC校验码 | |||
byte[] getCRC = sendByteList.ToArray(); | |||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | |||
sendByteList.Add(resultCRC[0]); | |||
sendByteList.Add(resultCRC[1]); | |||
byte[] sendByte = sendByteList.ToArray(); | |||
if (_serialPort.IsOpen) | |||
{ | |||
// 清空接收缓冲区(避免残留数据干扰) | |||
_serialPort.DiscardInBuffer(); | |||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||
Thread.Sleep(300); | |||
byte[] response = new byte[_serialPort.BytesToRead]; | |||
_serialPort.Read(response, 0, _serialPort.BytesToRead); | |||
return ParseRegistersresponse(response, numberOfPoints); | |||
} | |||
return null; | |||
} | |||
public ushort[] ParseRegistersresponse(byte[] response, ushort numberOfPoints) | |||
{ | |||
//判断发送回来的数据是否正确 | |||
CheckData.CheckResponse(response); | |||
if (!CRCUitl.ValidateCRC(response)) | |||
{ | |||
MessageBox.Show("0x14:CRC校验错误"); | |||
return null; | |||
} | |||
ushort[] registers = new ushort[numberOfPoints]; | |||
for (int i = 0; i < numberOfPoints; i++) | |||
{ | |||
int pos = 3 + i * 2; | |||
// 大端序转换 (高位在前) | |||
registers[i] = (ushort)((response[pos] << 8) | response[pos + 1]); | |||
} | |||
return registers; | |||
} | |||
} | |||
} |
@@ -7,6 +7,9 @@ using System.Windows.Markup; | |||
namespace ModbusDemo.Extension | |||
{ | |||
/// <summary> | |||
/// 此处代码是复制粘贴,用来让枚举类型绑定到下拉框上 | |||
/// </summary> | |||
class EnumBindingSourceExtension : MarkupExtension | |||
{ | |||
private Type _enumType; | |||
@@ -7,16 +7,18 @@ | |||
xmlns:local="clr-namespace:ModbusDemo" | |||
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" | |||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" | |||
xmlns:prism="http://prismlibrary.com/" | |||
xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" | |||
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel,IsDesignTimeCreatable=True}" | |||
xmlns:prism="http://prismlibrary.com/" | |||
xmlns:viewmodel="clr-namespace:ModbusDemo.VIewModel" | |||
Title="MainWindow" | |||
Width="900" | |||
Height="600" | |||
d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel, | |||
IsDesignTimeCreatable=True}" | |||
WindowStartupLocation="CenterScreen" | |||
mc:Ignorable="d"> | |||
<WindowChrome.WindowChrome> | |||
<WindowChrome GlassFrameThickness="-1"></WindowChrome> | |||
<WindowChrome GlassFrameThickness="-1"> | |||
</WindowChrome> | |||
</WindowChrome.WindowChrome> | |||
<md:DialogHost DialogTheme="Inherit" Identifier="RootDialog"> | |||
@@ -37,8 +39,13 @@ | |||
</i:Interaction.Triggers> | |||
<ListBox.ItemTemplate> | |||
<DataTemplate> | |||
<StackPanel Orientation="Horizontal" Background="Transparent" > | |||
<md:PackIcon Margin="15,0" HorizontalAlignment="Center" VerticalAlignment="Center" Kind="{Binding Icon}" FontSize="20"> | |||
<StackPanel Orientation="Horizontal" Background="Transparent"> | |||
<md:PackIcon | |||
Margin="15,0" | |||
HorizontalAlignment="Center" | |||
VerticalAlignment="Center" | |||
Kind="{Binding Icon}" | |||
FontSize="20"> | |||
</md:PackIcon> | |||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding MenuName}" FontSize="20"> | |||
</TextBlock> | |||
@@ -13,6 +13,12 @@ | |||
d:DesignHeight="450" | |||
d:DesignWidth="800" | |||
mc:Ignorable="d"> | |||
<UserControl.Resources> | |||
<Style TargetType="TextBox"> | |||
<Setter Property="Margin" Value="0,5"/> | |||
<Setter Property="FontSize" Value="14"/> | |||
</Style> | |||
</UserControl.Resources> | |||
<Grid> | |||
<Grid.RowDefinitions> | |||
<RowDefinition Height="60"> | |||
@@ -45,6 +51,10 @@ | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
</Grid.ColumnDefinitions> | |||
<Grid.RowDefinitions> | |||
<RowDefinition></RowDefinition> | |||
<RowDefinition Height="60"></RowDefinition> | |||
</Grid.RowDefinitions> | |||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="从站地址"> | |||
</TextBlock> | |||
@@ -66,11 +76,11 @@ | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Column="3" HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="读取结果"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding ReadResult}"> | |||
</TextBox> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="4" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<TextBlock Text="读取结果:" Margin="0,20,0,0" FontWeight="Black"/> | |||
<TextBox Margin="20,0,0,0" MinWidth="120" Text="{Binding ReadResult}" Style="{StaticResource MaterialDesignOutlinedTextBox}"/> | |||
</StackPanel> | |||
<Button | |||
Grid.Column="4" | |||
@@ -81,6 +91,7 @@ | |||
Content="读取" | |||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | |||
</Button> | |||
</Grid> | |||
<Grid Grid.Row="2"> | |||
<Grid.ColumnDefinitions> | |||
@@ -115,7 +126,12 @@ | |||
<TextBox Margin="0,-10,0,0" Text="{Binding WriteData}"> | |||
</TextBox> | |||
</StackPanel> | |||
<TextBlock Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" Text="1代表Ture,0代表flase"> | |||
<TextBlock | |||
Grid.Column="3" | |||
Margin="0,-50,0,0" | |||
HorizontalAlignment="Center" | |||
VerticalAlignment="Center" | |||
Text="1代表Ture,0代表flase"> | |||
</TextBlock> | |||
@@ -5,11 +5,147 @@ | |||
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:viewmodel="clr-namespace:ModbusDemo.VIewModel" | |||
d:DataContext="{d:DesignInstance Type=viewmodel:RegisterUCViewModel, | |||
IsDesignTimeCreatable=True}" | |||
d:DesignHeight="450" | |||
d:Background="White" | |||
d:DesignWidth="800" | |||
mc:Ignorable="d"> | |||
<UserControl.Resources> | |||
<Style TargetType="TextBox"> | |||
<Setter Property="Margin" Value="0,5" /> | |||
<Setter Property="FontSize" Value="14" /> | |||
</Style> | |||
</UserControl.Resources> | |||
<Grid> | |||
<TextBlock Text="Register" FontSize="30"> | |||
<Grid.RowDefinitions> | |||
<RowDefinition Height="60"> | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition> | |||
</RowDefinition> | |||
</Grid.RowDefinitions> | |||
<TextBlock | |||
HorizontalAlignment="Center" | |||
VerticalAlignment="Center" | |||
Text="{Binding SerialPortInfo}" | |||
FontWeight="Black" | |||
FontSize="16"> | |||
</TextBlock> | |||
<!-- 定义读取的数据 --> | |||
<Grid Grid.Row="1"> | |||
<Grid.ColumnDefinitions> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
</Grid.ColumnDefinitions> | |||
<Grid.RowDefinitions> | |||
<RowDefinition> | |||
</RowDefinition> | |||
<RowDefinition Height="60"> | |||
</RowDefinition> | |||
</Grid.RowDefinitions> | |||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="从站地址"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding SlaveAddress}"> | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Column="1" HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="起始地址"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding StartAddress}"> | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Column="2" HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="读取位数"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding NumberOfPoints}"> | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Row="2" Grid.ColumnSpan="4" HorizontalAlignment="Center" Orientation="Horizontal"> | |||
<TextBlock Margin="0,20,0,0" Text="读取结果:" FontWeight="Black" /> | |||
<TextBox MinWidth="120" Margin="20,0,0,0" Text="{Binding ReadResult}" Style="{StaticResource MaterialDesignOutlinedTextBox}" /> | |||
</StackPanel> | |||
<Button | |||
Grid.Column="4" | |||
Width="80" | |||
Height="30" | |||
materialDesign:ButtonAssist.CornerRadius="15" | |||
Command="{Binding ReadRegisterCmm}" | |||
Content="读取" | |||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | |||
</Button> | |||
</Grid> | |||
<Grid Grid.Row="2"> | |||
<Grid.ColumnDefinitions> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
<ColumnDefinition> | |||
</ColumnDefinition> | |||
</Grid.ColumnDefinitions> | |||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="从站地址"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding WriteSlaveAddress}"> | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Column="1" HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="起始地址"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding WriteStartAddress}"> | |||
</TextBox> | |||
</StackPanel> | |||
<StackPanel Grid.Column="2" HorizontalAlignment="Center" Orientation="Vertical"> | |||
<TextBlock Margin="20" Text="写入数据"> | |||
</TextBlock> | |||
<TextBox Margin="0,-10,0,0" Text="{Binding WriteData}"> | |||
</TextBox> | |||
</StackPanel> | |||
<TextBlock | |||
Grid.Column="3" | |||
Margin="0,-50,0,0" | |||
HorizontalAlignment="Center" | |||
VerticalAlignment="Center" | |||
Text="1代表Ture,0代表flase"> | |||
</TextBlock> | |||
<Button | |||
Grid.Column="4" | |||
Width="80" | |||
Height="30" | |||
materialDesign:ButtonAssist.CornerRadius="15" | |||
Command="{Binding WriteRegisterCmm}" | |||
Content="写入" | |||
Style="{StaticResource MaterialDesignRaisedDarkButton}"> | |||
</Button> | |||
</Grid> | |||
</Grid> | |||
</UserControl> |
@@ -1,13 +1,198 @@ | |||
using Prism.Mvvm; | |||
using ModbusDemo.Device; | |||
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; | |||
using System.Windows; | |||
namespace ModbusDemo.VIewModel | |||
{ | |||
class RegisterUCViewModel:BindableBase | |||
{ | |||
//获取读线圈的类 | |||
private IModbusRTU _modbusRTU; | |||
//定义读线圈的命令 | |||
public DelegateCommand ReadRegisterCmm { get; set; } | |||
//定义写线圈操作 | |||
public DelegateCommand WriteRegisterCmm { get; set; } | |||
//获取当前使用的串口 | |||
private SerialPort _serialPort; | |||
//显示当前链接串口的信息 | |||
public string SerialPortInfo | |||
{ | |||
get | |||
{ | |||
return "当前链接的状态:" + "串口号:" + _serialPort.PortName + ",波特率:" + _serialPort.BaudRate | |||
+ ",数据位:" + _serialPort.DataBits + ",校验位:" + _serialPort.Parity + ",停止位:" + _serialPort.StopBits; | |||
} | |||
} | |||
#region 读取定义 | |||
//读取的从站id | |||
private string _slaveAddress; | |||
public string SlaveAddress | |||
{ | |||
get { return _slaveAddress; } | |||
set | |||
{ | |||
_slaveAddress = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
//读取的起始地址 | |||
private string _startAddress; | |||
public string StartAddress | |||
{ | |||
get { return _startAddress; } | |||
set | |||
{ | |||
_startAddress = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
//读取的位数 | |||
private string _numberOfPoints; | |||
public string NumberOfPoints | |||
{ | |||
get { return _numberOfPoints; } | |||
set | |||
{ | |||
_numberOfPoints = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
private string _readResult; | |||
//读取的结果 | |||
public string ReadResult | |||
{ | |||
get { return _readResult; } | |||
set | |||
{ | |||
_readResult = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
#endregion | |||
#region 写入定义 | |||
//写入的从站id | |||
private string _writeslaveAddress; | |||
public string WriteSlaveAddress | |||
{ | |||
get { return _writeslaveAddress; } | |||
set | |||
{ | |||
_writeslaveAddress = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
//写入的起始地址 | |||
private string _writestartAddress; | |||
public string WriteStartAddress | |||
{ | |||
get { return _writestartAddress; } | |||
set | |||
{ | |||
_writestartAddress = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
//写入的数据 | |||
private string _writeData; | |||
public string WriteData | |||
{ | |||
get { return _writeData; } | |||
set | |||
{ | |||
_writeData = value; | |||
RaisePropertyChanged(); | |||
} | |||
} | |||
#endregion | |||
public RegisterUCViewModel() | |||
{ | |||
} | |||
public RegisterUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU) | |||
{ | |||
_serialPort = serialPort; | |||
ReadRegisterCmm = new DelegateCommand(ReadRegister); | |||
_modbusRTU = modbusRTU; | |||
WriteRegisterCmm = new DelegateCommand(WriteRegister); | |||
} | |||
/// <summary> | |||
/// 线圈读取操作 | |||
/// </summary> | |||
private void ReadRegister() | |||
{ | |||
try | |||
{ | |||
ushort[] result = _modbusRTU.ReadRegisters(byte.Parse(SlaveAddress), | |||
ushort.Parse(StartAddress), | |||
ushort.Parse(NumberOfPoints)); | |||
if (result != null) | |||
{ | |||
string temp = ""; | |||
foreach (var item in result) | |||
{ | |||
temp += item; | |||
temp += " "; | |||
} | |||
ReadResult = temp; | |||
} | |||
} | |||
catch (Exception) | |||
{ | |||
MessageBox.Show("参数配置错误"); | |||
} | |||
} | |||
private void WriteRegister() | |||
{ | |||
//去除字符串中的空格 | |||
WriteData = WriteData.Replace(" ", ""); | |||
//转换为布尔数组 | |||
bool[] data = WriteData.Select(m => m == '1').ToArray(); | |||
try | |||
{ | |||
_modbusRTU.WriteCoil(byte.Parse(WriteSlaveAddress), | |||
ushort.Parse(WriteStartAddress), | |||
data); | |||
} | |||
catch (Exception) | |||
{ | |||
MessageBox.Show("信息配置错误"); | |||
} | |||
} | |||
} | |||
} |
@@ -1,6 +1,7 @@ | |||
using ModbusDemo.Uitls; | |||
using Prism.Commands; | |||
using Prism.Mvvm; | |||
using Prism.Regions; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO.Ports; | |||
@@ -14,6 +15,9 @@ namespace ModbusDemo.VIewModel | |||
class SettingsUCViewModel : BindableBase | |||
{ | |||
//控制页面跳转 | |||
private readonly IRegionManager _regionManager; | |||
//断开连接的命令 | |||
public DelegateCommand DisConnectionCmm { get; set; } | |||
//链接窗口的命令 | |||
public DelegateCommand ConnectionCmm { get; set; } | |||
@@ -93,11 +97,12 @@ namespace ModbusDemo.VIewModel | |||
/// 从容器中获取创建的窗口 | |||
/// </summary> | |||
/// <param name="serialPort"></param> | |||
public SettingsUCViewModel(SerialPort serialPort) | |||
public SettingsUCViewModel(SerialPort serialPort, IRegionManager regionManager) | |||
{ | |||
_serialPort = serialPort; | |||
ConnectionCmm = new DelegateCommand(Connection); | |||
DisConnectionCmm = new DelegateCommand(DisConnection); | |||
_regionManager = regionManager; | |||
} | |||
private void DisConnection() | |||
@@ -127,6 +132,8 @@ namespace ModbusDemo.VIewModel | |||
_serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | |||
_serialPort.Open(); | |||
MessageBox.Show("串口链接成功"); | |||
_regionManager.Regions["ModbusRegion"].RequestNavigate("CoilUC"); | |||
} | |||
catch (Exception) | |||
{ | |||