Selaa lähdekoodia

读取寄存器

dev1
永攀 张 2 viikkoa sitten
vanhempi
commit
6f9e9a76e9
8 muutettua tiedostoa jossa 440 lisäystä ja 18 poistoa
  1. +2
    -0
      ModbusDemo/Device/IModbusRTU.cs
  2. +69
    -3
      ModbusDemo/Device/ModbusRTU.cs
  3. +3
    -0
      ModbusDemo/Extension/EnumBindingSourceExtension.cs
  4. +13
    -6
      ModbusDemo/MainWindow.xaml
  5. +22
    -6
      ModbusDemo/VIew/CoilUC.xaml
  6. +137
    -1
      ModbusDemo/VIew/RegisterUC.xaml
  7. +186
    -1
      ModbusDemo/VIewModel/RegisterUCViewModel.cs
  8. +8
    -1
      ModbusDemo/VIewModel/SettingsUCViewModel.cs

+ 2
- 0
ModbusDemo/Device/IModbusRTU.cs Näytä tiedosto

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

}
}

+ 69
- 3
ModbusDemo/Device/ModbusRTU.cs Näytä tiedosto

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

+ 3
- 0
ModbusDemo/Extension/EnumBindingSourceExtension.cs Näytä tiedosto

@@ -7,6 +7,9 @@ using System.Windows.Markup;

namespace ModbusDemo.Extension
{
/// <summary>
/// 此处代码是复制粘贴,用来让枚举类型绑定到下拉框上
/// </summary>
class EnumBindingSourceExtension : MarkupExtension
{
private Type _enumType;


+ 13
- 6
ModbusDemo/MainWindow.xaml Näytä tiedosto

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


+ 22
- 6
ModbusDemo/VIew/CoilUC.xaml Näytä tiedosto

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




+ 137
- 1
ModbusDemo/VIew/RegisterUC.xaml Näytä tiedosto

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

+ 186
- 1
ModbusDemo/VIewModel/RegisterUCViewModel.cs Näytä tiedosto

@@ -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("信息配置错误");
}

}
}
}

+ 8
- 1
ModbusDemo/VIewModel/SettingsUCViewModel.cs Näytä tiedosto

@@ -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)
{


Ladataan…
Peruuta
Tallenna