Przeglądaj źródła

写多个线圈操作

dev1
永攀 张 2 tygodni temu
rodzic
commit
48b12eafde
5 zmienionych plików z 245 dodań i 48 usunięć
  1. +24
    -17
      ModbusDemo/App.xaml
  2. +4
    -0
      ModbusDemo/Device/IModbusRTU.cs
  3. +73
    -5
      ModbusDemo/Device/ModbusRTU.cs
  4. +69
    -13
      ModbusDemo/VIew/CoilUC.xaml
  5. +75
    -13
      ModbusDemo/VIewModel/CoilUCViewModel.cs

+ 24
- 17
ModbusDemo/App.xaml Wyświetl plik

@@ -1,40 +1,47 @@
<prism:PrismApplication x:Class="ModbusDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ModbusDemo"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
>
<prism:PrismApplication
x:Class="ModbusDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ModbusDemo"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- 使用捆绑的主题,设置基础主题为浅色,主色为深紫色,次色为酸橙色 -->
<!-- 使用捆绑的主题,设置基础主题为浅色,主色为深紫色,次色为酸橙色 -->
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="LightBlue" SecondaryColor="Lime" />

<!-- 引用 Material Design 2 的默认样式 -->
<!-- 引用 Material Design 2 的默认样式 -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>

<Style x:Key="LeftMenuStyle" TargetType="ListBoxItem">
<Setter Property="MinHeight" Value="40"></Setter>
<Setter Property="MinHeight" Value="40">
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="border"></Border>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"></ContentPresenter>
<Border x:Name="border">
</Border>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
</ContentPresenter>
</Grid>

<!--触发器-->
<!-- 触发器 -->
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="border" Property="Background" Value="{DynamicResource PrimaryHueLightBrush}"></Setter>
<Setter TargetName="border" Property="Opacity" Value="0.2"></Setter>
<Setter TargetName="border" Property="Background" Value="{DynamicResource PrimaryHueLightBrush}">
</Setter>
<Setter TargetName="border" Property="Opacity" Value="0.2">
</Setter>
</Trigger>

<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{DynamicResource PrimaryHueLightBrush}"></Setter>
<Setter TargetName="border" Property="Opacity" Value="0.2"></Setter>
<Setter TargetName="border" Property="Background" Value="{DynamicResource PrimaryHueLightBrush}">
</Setter>
<Setter TargetName="border" Property="Opacity" Value="0.2">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>


+ 4
- 0
ModbusDemo/Device/IModbusRTU.cs Wyświetl plik

@@ -9,5 +9,9 @@ namespace ModbusDemo.Device
interface IModbusRTU
{
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints);


public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data);

}
}

+ 73
- 5
ModbusDemo/Device/ModbusRTU.cs Wyświetl plik

@@ -26,7 +26,11 @@ namespace ModbusDemo.Device
/// <returns></returns>
public bool[] ReadCoil(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
{

if (!_serialPort.IsOpen)
{
MessageBox.Show("串口没有链接,请先链接");
return null;
}
List<byte> sendByteList = new List<byte>();
//设置从站地址
sendByteList.Add(slaveAddress);
@@ -89,20 +93,84 @@ namespace ModbusDemo.Device
}
//先将字符串转为数组,再反转,再转为字节数组
char[] chars = result.ToArray().Reverse<char>().ToArray();
bool[] f = new bool[numberOfPoints];
bool[] ultimately = new bool[numberOfPoints];
for (int i = 0; i < numberOfPoints; i++)
{
if (chars[i] == '1')
{
f[i] = true;
ultimately[i] = true;
}
else
{
f[i] = false;
ultimately[i] = false;
}
}
return f;
return ultimately;
}

public void WriteCoil(byte slaveAddress, ushort startAddress, bool[] data)
{
List<byte> sendByteList = new List<byte>();
//设置从站地址
sendByteList.Add(slaveAddress);
//设置功能码
sendByteList.Add(0x0F);
//设置起始地址的高位和低位
sendByteList.Add(BitConverter.GetBytes(startAddress)[1]);
sendByteList.Add(BitConverter.GetBytes(startAddress)[0]);
//设置写入几个线圈
sendByteList.Add(BitConverter.GetBytes(data.Length)[1]);
sendByteList.Add(BitConverter.GetBytes(data.Length)[0]);

// 计算字节数
int byteCount = (data.Length + 7) / 8;
sendByteList.Add((byte)byteCount);

// 初始化字节数组
byte[] coilBytes = new byte[byteCount];

// 把bool数组转换为字节
for (int i = 0; i < data.Length; i++)
{
int byteIndex = i / 8;
int bitIndex = i % 8;
if (data[i])
{
coilBytes[byteIndex] |= (byte)(1 << bitIndex);
}
}
sendByteList.AddRange(coilBytes);

//获取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);

//判断发送回来的数据是否正确
CheckData.CheckResponse(response);

if (!CRCUitl.ValidateCRC(response))
{
MessageBox.Show("0x14:CRC校验错误");
}
}


}
}
}

+ 69
- 13
ModbusDemo/VIew/CoilUC.xaml Wyświetl plik

@@ -31,6 +31,7 @@
FontWeight="Black"
FontSize="16">
</TextBlock>
<!-- 定义读取的数据 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition>
@@ -44,34 +45,89 @@
<ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<TextBlock Text="从站地址" Margin="20"></TextBlock>
<TextBox Text="{Binding SlaveAddress}" Margin="0,-10,0,0"></TextBox>
<StackPanel HorizontalAlignment="Center" Orientation="Vertical">
<TextBlock Margin="20" Text="从站地址">
</TextBlock>
<TextBox Margin="0,-10,0,0" Text="{Binding SlaveAddress}">
</TextBox>
</StackPanel>

<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Grid.Column="1">
<TextBlock Text="起始地址" Margin="20"></TextBlock>
<TextBox Text="{Binding StartAddress}" Margin="0,-10,0,0"></TextBox>
<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 Orientation="Vertical" HorizontalAlignment="Center" Grid.Column="2">
<TextBlock Text="读取位数" Margin="20"></TextBlock>
<TextBox Text="{Binding NumberOfPoints}" Margin="0,-10,0,0"></TextBox>
<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 Orientation="Vertical" HorizontalAlignment="Center" Grid.Column="3">
<TextBlock Text="读取结果" Margin="20"></TextBlock>
<TextBox Text="{Binding ReadResult}" Margin="0,-10,0,0"></TextBox>
<StackPanel Grid.Column="3" HorizontalAlignment="Center" Orientation="Vertical">
<TextBlock Margin="20" Text="读取结果">
</TextBlock>
<TextBox Margin="0,-10,0,0" Text="{Binding ReadResult}">
</TextBox>
</StackPanel>
<Button
Grid.Column="4"
Width="80"
Height="30"
Command="{Binding ReadCoilCmm}"
materialDesign:ButtonAssist.CornerRadius="15"
Command="{Binding ReadCoilCmm}"
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" HorizontalAlignment="Center" VerticalAlignment="Center" Text="1代表Ture,0代表flase">
</TextBlock>


<Button
Grid.Column="4"
Width="80"
Height="30"
materialDesign:ButtonAssist.CornerRadius="15"
Command="{Binding WriteCoilCmm}"
Content="写入"
Style="{StaticResource MaterialDesignRaisedDarkButton}">
</Button>
</Grid>
</Grid>
</UserControl>

+ 75
- 13
ModbusDemo/VIewModel/CoilUCViewModel.cs Wyświetl plik

@@ -20,6 +20,8 @@ namespace ModbusDemo.VIewModel
private IModbusRTU _modbusRTU;
//定义读线圈的命令
public DelegateCommand ReadCoilCmm { get; set; }
//定义写线圈操作
public DelegateCommand WriteCoilCmm { get; set; }
//获取当前使用的串口
private SerialPort _serialPort;
//显示当前链接串口的信息
@@ -32,7 +34,7 @@ namespace ModbusDemo.VIewModel
}

}
#region 读取定义

//读取的从站id
private string _slaveAddress;
@@ -46,10 +48,10 @@ namespace ModbusDemo.VIewModel
RaisePropertyChanged();
}
}
//读取的起始地址
private string _startAddress;

//读取的起始地址
public string StartAddress
{
get { return _startAddress; }
@@ -59,10 +61,10 @@ namespace ModbusDemo.VIewModel
RaisePropertyChanged();
}
}
//读取的位数
private string _numberOfPoints;

//读取的位数
public string NumberOfPoints
{
get { return _numberOfPoints; }
@@ -85,9 +87,51 @@ namespace ModbusDemo.VIewModel
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 CoilUCViewModel()
{

@@ -98,30 +142,31 @@ namespace ModbusDemo.VIewModel
_serialPort = serialPort;
ReadCoilCmm = new DelegateCommand(ReadCoil);
_modbusRTU = modbusRTU;
WriteCoilCmm = new DelegateCommand(WriteCoil);
}

private void ReadCoil()
{


/// <summary>
/// 线圈读取操作
/// </summary>
private void ReadCoil()
{
try
{
bool[] result = _modbusRTU.ReadCoil(byte.Parse(SlaveAddress),
ushort.Parse(StartAddress),
ushort.Parse(NumberOfPoints));

if(result != null)
if (result != null)
{
string temp = "";
foreach(var item in result)
foreach (var item in result)
{
temp += item;
temp += " ";
}
ReadResult = temp;
}
}
catch (Exception)
{
@@ -129,9 +174,26 @@ namespace ModbusDemo.VIewModel
MessageBox.Show("参数配置错误");
}

}
private void WriteCoil()
{
//去除字符串中的空格
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("信息配置错误");
}
}
}
}

Ładowanie…
Anuluj
Zapisz