@@ -25,7 +25,7 @@ namespace ModbusDemo.Device | |||||
{ | { | ||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
_modbusDbContext = modbusDbContext; | _modbusDbContext = modbusDbContext; | ||||
_portAdapter = new SerialPortAdapter(serialPort); | |||||
//_portAdapter = new SerialPortAdapter(serialPort); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 用来发送读写线圈的指令 | /// 用来发送读写线圈的指令 | ||||
@@ -63,11 +63,20 @@ namespace ModbusDemo.Device | |||||
int attempt = 0; | int attempt = 0; | ||||
byte[] response = null; | byte[] response = null; | ||||
List<byte> responseData = new List<byte>(); | List<byte> responseData = new List<byte>(); | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
while (attempt < maxRetries) | while (attempt < maxRetries) | ||||
{ | { | ||||
if (_serialPort.IsOpen) | |||||
{ | |||||
// 每次重试前清空缓冲区 | |||||
responseData.Clear(); | |||||
// 清除输入缓冲区残留数据 | |||||
_serialPort.DiscardInBuffer(); | |||||
} | |||||
try | try | ||||
{ | { | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
//使用时间去轮询查询数据 | //使用时间去轮询查询数据 | ||||
DateTime startTime = DateTime.Now; | DateTime startTime = DateTime.Now; | ||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | ||||
@@ -80,11 +89,12 @@ namespace ModbusDemo.Device | |||||
responseData.AddRange(buffer.Take(bytesRead)); | responseData.AddRange(buffer.Take(bytesRead)); | ||||
} | } | ||||
//延迟20毫秒,节约cpu资源 | //延迟20毫秒,节约cpu资源 | ||||
Task.Delay(20); | |||||
Thread.Sleep(20); | |||||
} | } | ||||
response = responseData.ToArray(); | response = responseData.ToArray(); | ||||
if (response[0] == 0x00) | |||||
if (response.Length == 0) | |||||
{ | { | ||||
attempt++; | |||||
continue; | continue; | ||||
} | } | ||||
resultValue = ParseCoilresponse(sendByte, response, numberOfPoints); | resultValue = ParseCoilresponse(sendByte, response, numberOfPoints); | ||||
@@ -93,6 +103,10 @@ namespace ModbusDemo.Device | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
} | |||||
finally | |||||
{ | |||||
attempt++; | attempt++; | ||||
} | } | ||||
@@ -112,7 +126,7 @@ namespace ModbusDemo.Device | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("0x15:数据库插入错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.DatabaseException.ToString()); | |||||
} | } | ||||
return resultValue; | return resultValue; | ||||
@@ -132,17 +146,17 @@ namespace ModbusDemo.Device | |||||
//将操作的指令,插入数据库 | //将操作的指令,插入数据库 | ||||
string RequestStr = ByteArrayToString(sendByte); | string RequestStr = ByteArrayToString(sendByte); | ||||
string responseStr = ByteArrayToString(response); | string responseStr = ByteArrayToString(response); | ||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "读线圈"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
ModbusLog modbusLog = new ModbusLog(); | |||||
modbusLog.OperationType = "读线圈"; | |||||
modbusLog.ResponseData = responseStr; | |||||
modbusLog.RequestData = RequestStr; | |||||
_modbusDbContext.Add(modbusLog); | |||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("0x15:数据库插入错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.DatabaseException.ToString()); | |||||
} | } | ||||
@@ -222,11 +236,19 @@ namespace ModbusDemo.Device | |||||
int attempt = 0; | int attempt = 0; | ||||
byte[] response = null; | byte[] response = null; | ||||
List<byte> responseData = new List<byte>(); | List<byte> responseData = new List<byte>(); | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
while (attempt < maxRetries) | while (attempt < maxRetries) | ||||
{ | { | ||||
if (_serialPort.IsOpen) | |||||
{ | |||||
// 每次重试前清空缓冲区 | |||||
responseData.Clear(); | |||||
// 清除输入缓冲区残留数据 | |||||
_serialPort.DiscardInBuffer(); | |||||
} | |||||
try | try | ||||
{ | { | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
//使用时间去轮询查询数据 | //使用时间去轮询查询数据 | ||||
DateTime startTime = DateTime.Now; | DateTime startTime = DateTime.Now; | ||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | ||||
@@ -239,10 +261,10 @@ namespace ModbusDemo.Device | |||||
responseData.AddRange(buffer.Take(bytesRead)); | responseData.AddRange(buffer.Take(bytesRead)); | ||||
} | } | ||||
//延迟20毫秒,节约cpu资源 | //延迟20毫秒,节约cpu资源 | ||||
Task.Delay(20); | |||||
Thread.Sleep(20); | |||||
} | } | ||||
response = responseData.ToArray(); | response = responseData.ToArray(); | ||||
if (response[0] != 0x00) | |||||
if (response.Length != 0) | |||||
{ | { | ||||
break; | break; | ||||
} | } | ||||
@@ -250,6 +272,10 @@ namespace ModbusDemo.Device | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
} | |||||
finally | |||||
{ | |||||
attempt++; | attempt++; | ||||
} | } | ||||
@@ -260,16 +286,16 @@ namespace ModbusDemo.Device | |||||
//将操作的指令,插入数据库 | //将操作的指令,插入数据库 | ||||
string RequestStr = ByteArrayToString(sendByte); | string RequestStr = ByteArrayToString(sendByte); | ||||
string responseStr = ByteArrayToString(response); | string responseStr = ByteArrayToString(response); | ||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "写线圈"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
ModbusLog modbusLog = new ModbusLog(); | |||||
modbusLog.OperationType = "写线圈"; | |||||
modbusLog.ResponseData = responseStr; | |||||
modbusLog.RequestData = RequestStr; | |||||
_modbusDbContext.Add(modbusLog); | |||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("0x15:数据库插入错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.DatabaseException.ToString()); | |||||
} | } | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
@@ -334,12 +360,18 @@ namespace ModbusDemo.Device | |||||
int attempt = 0; | int attempt = 0; | ||||
List<byte> responseData = new List<byte>(); | List<byte> responseData = new List<byte>(); | ||||
byte[] response = null; | byte[] response = null; | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
while (attempt < maxRetries) | while (attempt < maxRetries) | ||||
{ | { | ||||
if (_serialPort.IsOpen) | |||||
{ | |||||
// 每次重试前清空缓冲区 | |||||
responseData.Clear(); | |||||
// 清除输入缓冲区残留数据 | |||||
_serialPort.DiscardInBuffer(); | |||||
} | |||||
try | try | ||||
{ | { | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
//使用时间去轮询查询数据 | //使用时间去轮询查询数据 | ||||
DateTime startTime = DateTime.Now; | DateTime startTime = DateTime.Now; | ||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | ||||
@@ -352,10 +384,10 @@ namespace ModbusDemo.Device | |||||
responseData.AddRange(buffer.Take(bytesRead)); | responseData.AddRange(buffer.Take(bytesRead)); | ||||
} | } | ||||
//延迟20毫秒,节约cpu资源 | //延迟20毫秒,节约cpu资源 | ||||
Task.Delay(20); | |||||
Thread.Sleep(20); | |||||
} | } | ||||
response = responseData.ToArray(); | response = responseData.ToArray(); | ||||
if (response[0] == 0x00) | |||||
if (response.Length == 0) | |||||
{ | { | ||||
continue; | continue; | ||||
} | } | ||||
@@ -365,26 +397,31 @@ namespace ModbusDemo.Device | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
} | |||||
finally | |||||
{ | |||||
attempt++; | attempt++; | ||||
} | } | ||||
} | } | ||||
//将操作失败的指令,插入数据库 | |||||
string RequestStr = ByteArrayToString(sendByte); | |||||
try | try | ||||
{ | { | ||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "读寄存器"; | |||||
m.ResponseData = ""; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
//将操作失败的指令,插入数据库 | |||||
string RequestStr = ByteArrayToString(sendByte); | |||||
ModbusLog modbusLog = new ModbusLog(); | |||||
modbusLog.OperationType = "读寄存器"; | |||||
modbusLog.ResponseData = ""; | |||||
modbusLog.RequestData = RequestStr; | |||||
_modbusDbContext.Add(modbusLog); | |||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("0x15:数据库插入错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.DatabaseException.ToString()); | |||||
} | } | ||||
return resultValue; | return resultValue; | ||||
@@ -406,16 +443,16 @@ namespace ModbusDemo.Device | |||||
//将操作的指令,插入数据库 | //将操作的指令,插入数据库 | ||||
string RequestStr = ByteArrayToString(sendByte); | string RequestStr = ByteArrayToString(sendByte); | ||||
string responseStr = ByteArrayToString(response); | string responseStr = ByteArrayToString(response); | ||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "读寄存器"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
ModbusLog modbusLog = new ModbusLog(); | |||||
modbusLog.OperationType = "读寄存器"; | |||||
modbusLog.ResponseData = responseStr; | |||||
modbusLog.RequestData = RequestStr; | |||||
_modbusDbContext.Add(modbusLog); | |||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("0x15:数据库插入错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.DatabaseException.ToString()); | |||||
} | } | ||||
@@ -493,11 +530,19 @@ namespace ModbusDemo.Device | |||||
int attempt = 0; | int attempt = 0; | ||||
byte[] response = null; | byte[] response = null; | ||||
List<byte> responseData = new List<byte>(); | List<byte> responseData = new List<byte>(); | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
while (attempt < maxRetries) | while (attempt < maxRetries) | ||||
{ | { | ||||
if (_serialPort.IsOpen) | |||||
{ | |||||
// 每次重试前清空缓冲区 | |||||
responseData.Clear(); | |||||
// 清除输入缓冲区残留数据 | |||||
_serialPort.DiscardInBuffer(); | |||||
} | |||||
try | try | ||||
{ | { | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
//使用时间去轮询查询数据 | //使用时间去轮询查询数据 | ||||
DateTime startTime = DateTime.Now; | DateTime startTime = DateTime.Now; | ||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | ||||
@@ -510,15 +555,19 @@ namespace ModbusDemo.Device | |||||
responseData.AddRange(buffer.Take(bytesRead)); | responseData.AddRange(buffer.Take(bytesRead)); | ||||
} | } | ||||
//延迟20毫秒,节约cpu资源 | //延迟20毫秒,节约cpu资源 | ||||
Task.Delay(20); | |||||
Thread.Sleep(20); | |||||
} | } | ||||
response = responseData.ToArray(); | response = responseData.ToArray(); | ||||
if (response[0] != 0x00) | |||||
if (response.Length != 0) | |||||
{ | { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | |||||
} | |||||
finally | |||||
{ | { | ||||
attempt++; | attempt++; | ||||
} | } | ||||
@@ -528,11 +577,11 @@ namespace ModbusDemo.Device | |||||
//将操作的指令,插入数据库 | //将操作的指令,插入数据库 | ||||
string RequestStr = ByteArrayToString(sendByte); | string RequestStr = ByteArrayToString(sendByte); | ||||
string responseStr = ByteArrayToString(response); | string responseStr = ByteArrayToString(response); | ||||
ModbusLog m = new ModbusLog(); | |||||
m.OperationType = "写寄存器"; | |||||
m.ResponseData = responseStr; | |||||
m.RequestData = RequestStr; | |||||
_modbusDbContext.Add(m); | |||||
ModbusLog modbusLog = new ModbusLog(); | |||||
modbusLog.OperationType = "写寄存器"; | |||||
modbusLog.ResponseData = responseStr; | |||||
modbusLog.RequestData = RequestStr; | |||||
_modbusDbContext.Add(modbusLog); | |||||
_modbusDbContext.SaveChanges(); | _modbusDbContext.SaveChanges(); | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
@@ -0,0 +1,52 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace ModbusDemo.ErrorCode | |||||
{ | |||||
public class ErrorCode | |||||
{ | |||||
// 静态列表:存储所有错误码 | |||||
public static readonly List<ErrorCode> AllErrors = new List<ErrorCode>(); | |||||
// 错误码值 | |||||
public byte Code { get; } | |||||
// 错误描述 | |||||
public string Description { get; } | |||||
// 私有构造函数,只能通过静态方法创建错误码 | |||||
private ErrorCode(byte code, string description) | |||||
{ | |||||
Code = code; | |||||
Description = description; | |||||
// 自动添加到错误码列表 | |||||
AllErrors.Add(this); | |||||
} | |||||
// 重写 ToString 方法 | |||||
public override string ToString() => $"Error 0x{Code:X2}: {Description}"; | |||||
// 隐式转换为 byte | |||||
public static implicit operator byte(ErrorCode error) => error.Code; | |||||
// 根据错误码值查找错误码 | |||||
public static ErrorCode FromByte(byte code) => AllErrors.FirstOrDefault(e => e.Code == code); | |||||
// 定义所有错误码 | |||||
public static readonly ErrorCode FunctionCodeError = new ErrorCode(0x01, "功能码错误"); | |||||
public static readonly ErrorCode DomainStartAddressError = new ErrorCode(0x02, "域数据首地址错误"); | |||||
public static readonly ErrorCode DataContentError = new ErrorCode(0x03, "数据内容错误"); | |||||
public static readonly ErrorCode DataTypeError = new ErrorCode(0x10, "数据类型错误"); | |||||
public static readonly ErrorCode DomainDataCountError = new ErrorCode(0x11, "域数据个数错误"); | |||||
public static readonly ErrorCode DataCountMismatch = new ErrorCode(0x12, "数据个数与内部区域数据个数不符"); | |||||
public static readonly ErrorCode WriteOperationDenied = new ErrorCode(0x13, "不能进行写操作"); | |||||
public static readonly ErrorCode CrcCheckError = new ErrorCode(0x14, "CRC校验错误"); | |||||
public static readonly ErrorCode DatabaseException = new ErrorCode(0x15, "数据库异常"); | |||||
} | |||||
} |
@@ -4,7 +4,8 @@ using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Windows.Markup; | using System.Windows.Markup; | ||||
using System; | |||||
using System.Reflection; | |||||
namespace ModbusDemo.Extension | namespace ModbusDemo.Extension | ||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
@@ -9,6 +9,11 @@ | |||||
<ApplicationIcon>ModbusRTU_64x64.ico</ApplicationIcon> | <ApplicationIcon>ModbusRTU_64x64.ico</ApplicationIcon> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | |||||
<Compile Remove="ErrorCode\ErrorCodeExtensions.cs" /> | |||||
<Compile Remove="ErrorCode\ErrorInfoAttribute.cs" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<Content Include="ModbusRTU_64x64.ico"> | <Content Include="ModbusRTU_64x64.ico"> | ||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
@@ -0,0 +1,10 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace ModbusDemo.Model | |||||
{ | |||||
} |
@@ -4,7 +4,7 @@ using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Windows; | using System.Windows; | ||||
using ModbusDemo.ErrorCode; | |||||
namespace ModbusDemo.Uitls | namespace ModbusDemo.Uitls | ||||
{ | { | ||||
public static class CheckData | public static class CheckData | ||||
@@ -32,7 +32,9 @@ namespace ModbusDemo.Uitls | |||||
// 判断高4位是否等于8 | // 判断高4位是否等于8 | ||||
if (highNibble == 8) | if (highNibble == 8) | ||||
{ | { | ||||
MessageBox.Show($"数据错误:错误码为:0x{response[2]:X2}"); | |||||
var error = ErrorCode.ErrorCode.FromByte(response[2]); | |||||
MessageBox.Show(error.ToString()); | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
@@ -40,7 +42,7 @@ namespace ModbusDemo.Uitls | |||||
if (!CRCUitl.ValidateCRC(response)) | if (!CRCUitl.ValidateCRC(response)) | ||||
{ | { | ||||
MessageBox.Show("0x14:CRC校验错误"); | |||||
MessageBox.Show(ErrorCode.ErrorCode.CrcCheckError.ToString()); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -31,7 +31,6 @@ | |||||
<RowDefinition> | <RowDefinition> | ||||
</RowDefinition> | </RowDefinition> | ||||
</Grid.RowDefinitions> | </Grid.RowDefinitions> | ||||
<Grid Grid.Row="1"> | <Grid Grid.Row="1"> | ||||
<Grid.ColumnDefinitions> | <Grid.ColumnDefinitions> | ||||
<ColumnDefinition> | <ColumnDefinition> | ||||
@@ -44,7 +43,8 @@ | |||||
</ColumnDefinition> | </ColumnDefinition> | ||||
<ColumnDefinition> | <ColumnDefinition> | ||||
</ColumnDefinition> | </ColumnDefinition> | ||||
<ColumnDefinition> | |||||
</ColumnDefinition> | |||||
</Grid.ColumnDefinitions> | </Grid.ColumnDefinitions> | ||||
<!-- 这是设置串口的选择 --> | <!-- 这是设置串口的选择 --> | ||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> | <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> | ||||
@@ -131,6 +131,32 @@ | |||||
</ComboBox> | </ComboBox> | ||||
</StackPanel> | </StackPanel> | ||||
<!-- 超时时间 --> | |||||
<StackPanel Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Center"> | |||||
<TextBlock Margin="10,0,0,5" Text="超时时间"> | |||||
</TextBlock> | |||||
<ComboBox | |||||
Width="80" | |||||
Height="30" | |||||
Margin="10,0,0,5" | |||||
HorizontalAlignment="Left" | |||||
materialDesign:HintAssist.Hint="200" | |||||
SelectedItem="{Binding TimeOut}"> | |||||
<ComboBoxItem Content="20"> | |||||
</ComboBoxItem> | |||||
<ComboBoxItem Content="50"> | |||||
</ComboBoxItem> | |||||
<ComboBoxItem Content="100"> | |||||
</ComboBoxItem> | |||||
<ComboBoxItem Content="200"> | |||||
</ComboBoxItem> | |||||
<ComboBoxItem Content="300"> | |||||
</ComboBoxItem> | |||||
<ComboBoxItem Content="500"> | |||||
</ComboBoxItem> | |||||
</ComboBox> | |||||
</StackPanel> | |||||
</Grid> | </Grid> | ||||
<!-- 两个按钮的定义 --> | <!-- 两个按钮的定义 --> | ||||
<Grid Grid.Row="2"> | <Grid Grid.Row="2"> | ||||
@@ -50,7 +50,7 @@ namespace ModbusDemo.VIewModel | |||||
} | } | ||||
public AttachUCViewModel(SerialPort serialPort) | public AttachUCViewModel(SerialPort serialPort) | ||||
{ | { | ||||
ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister); | |||||
ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister2); | |||||
_serialPort = serialPort; | _serialPort = serialPort; | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -124,18 +124,18 @@ namespace ModbusDemo.VIewModel | |||||
ushort currentChunkSize = 100; | ushort currentChunkSize = 100; | ||||
int chunkIndex = i; | int chunkIndex = i; | ||||
tasks[i] = Task.Run(async () => | |||||
{ | |||||
ushort[] registers = await ReadRegisters(slaveId, startAddress, currentChunkSize); | |||||
ushort[] registers = ReadRegisters(slaveId, startAddress, currentChunkSize); | |||||
Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); | Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); | ||||
}); | |||||
} | } | ||||
// 等待所有任务完成 | // 等待所有任务完成 | ||||
Task.WaitAll(tasks); | |||||
Time = (int)(DateTime.Now - startTime).TotalMilliseconds; | Time = (int)(DateTime.Now - startTime).TotalMilliseconds; | ||||
StringBuilder result = new StringBuilder(); | StringBuilder result = new StringBuilder(); | ||||
int count = 0; | int count = 0; | ||||
@@ -151,27 +151,25 @@ namespace ModbusDemo.VIewModel | |||||
ReadResult = result.ToString(); | ReadResult = result.ToString(); | ||||
} | } | ||||
public async Task<ushort[]> ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | |||||
public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) | |||||
{ | { | ||||
ushort[] resultValue = null; | ushort[] resultValue = null; | ||||
if (!_serialPort.IsOpen) | if (!_serialPort.IsOpen) | ||||
{ | { | ||||
MessageBox.Show("串口没有链接,请先链接"); | MessageBox.Show("串口没有链接,请先链接"); | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
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]); | |||||
var sendByteList = new List<byte>(8) | |||||
{ | |||||
slaveAddress, // 从站地址 | |||||
0x03, // 功能码:读保持寄存器 | |||||
}; | |||||
// 添加起始地址(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); | |||||
// 添加读取点数(高字节在前) | |||||
sendByteList.AddRange(BitConverter.GetBytes(numberOfPoints).Reverse()); | |||||
//获取CRC校验码 | //获取CRC校验码 | ||||
byte[] getCRC = sendByteList.ToArray(); | byte[] getCRC = sendByteList.ToArray(); | ||||
byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); | ||||
@@ -183,14 +181,15 @@ namespace ModbusDemo.VIewModel | |||||
int attempt = 0; | int attempt = 0; | ||||
List<byte> responseData = new List<byte>(); | List<byte> responseData = new List<byte>(); | ||||
byte[] response = null; | byte[] response = null; | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
while (attempt < maxRetries) | while (attempt < maxRetries) | ||||
{ | { | ||||
// 每次重试前清空缓冲区 | |||||
responseData.Clear(); | |||||
// 清除输入缓冲区残留数据 | |||||
_serialPort.DiscardInBuffer(); | |||||
try | try | ||||
{ | { | ||||
_serialPort.Write(sendByte, 0, sendByte.Length); | |||||
//使用时间去轮询查询数据 | //使用时间去轮询查询数据 | ||||
DateTime startTime = DateTime.Now; | DateTime startTime = DateTime.Now; | ||||
while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) | ||||
@@ -203,33 +202,42 @@ namespace ModbusDemo.VIewModel | |||||
responseData.AddRange(buffer.Take(bytesRead)); | responseData.AddRange(buffer.Take(bytesRead)); | ||||
} | } | ||||
//延迟20毫秒,节约cpu资源 | //延迟20毫秒,节约cpu资源 | ||||
await Task.Delay(20); | |||||
Thread.Sleep(20); | |||||
} | } | ||||
response = responseData.ToArray(); | response = responseData.ToArray(); | ||||
if (response[0] == 0x00) | |||||
if (response.Length == 0) | |||||
{ | { | ||||
continue; | continue; | ||||
} | } | ||||
resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); | resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
} | |||||
finally | |||||
{ | |||||
attempt++; | attempt++; | ||||
} | } | ||||
} | } | ||||
return resultValue; | return resultValue; | ||||
} | } | ||||
/// <summary> | |||||
/// 解析读取到的操作 | |||||
/// </summary> | |||||
/// <param name="sendByte"></param> | |||||
/// <param name="response"></param> | |||||
/// <param name="numberOfPoints"></param> | |||||
/// <returns></returns> | |||||
public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) | public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) | ||||
{ | { | ||||
//判断发送回来的数据是否正确 | //判断发送回来的数据是否正确 | ||||
@@ -249,7 +257,12 @@ namespace ModbusDemo.VIewModel | |||||
{ | { | ||||
return null; | return null; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -14,7 +14,7 @@ using System.Windows; | |||||
namespace ModbusDemo.VIewModel | namespace ModbusDemo.VIewModel | ||||
{ | { | ||||
class SettingsUCViewModel : BindableBase | class SettingsUCViewModel : BindableBase | ||||
{ | { | ||||
//事件聚合器 | //事件聚合器 | ||||
@@ -22,9 +22,9 @@ namespace ModbusDemo.VIewModel | |||||
//控制页面跳转 | //控制页面跳转 | ||||
private readonly IRegionManager _regionManager; | private readonly IRegionManager _regionManager; | ||||
//断开连接的命令 | //断开连接的命令 | ||||
public DelegateCommand DisConnectionCmm { get; set; } | |||||
public DelegateCommand DisConnectionCmm { get; set; } | |||||
//链接窗口的命令 | //链接窗口的命令 | ||||
public DelegateCommand ConnectionCmm { get; set; } | |||||
public DelegateCommand ConnectionCmm { get; set; } | |||||
//获取串口 | //获取串口 | ||||
private SerialPort _serialPort; | private SerialPort _serialPort; | ||||
@@ -93,9 +93,23 @@ namespace ModbusDemo.VIewModel | |||||
} | } | ||||
} | } | ||||
//设置读取和写入时间 | |||||
private string _timeOut = "200"; | |||||
public string TimeOut | |||||
{ | |||||
get { return _timeOut; } | |||||
set | |||||
{ | |||||
_timeOut = value; | |||||
RaisePropertyChanged(); | |||||
} | |||||
} | |||||
public SettingsUCViewModel() | public SettingsUCViewModel() | ||||
{ | { | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 从容器中获取创建的窗口 | /// 从容器中获取创建的窗口 | ||||
@@ -115,7 +129,7 @@ namespace ModbusDemo.VIewModel | |||||
if (_serialPort.IsOpen) | if (_serialPort.IsOpen) | ||||
{ | { | ||||
_serialPort.Close(); | _serialPort.Close(); | ||||
} | } | ||||
MessageBox.Show("连接已经断开"); | MessageBox.Show("连接已经断开"); | ||||
} | } | ||||
@@ -139,11 +153,11 @@ namespace ModbusDemo.VIewModel | |||||
} | } | ||||
_serialPort.StopBits = this.StopBits; | _serialPort.StopBits = this.StopBits; | ||||
_serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | _serialPort.DataBits = int.Parse(GetComboBoxItemValue(this.DataBits)); | ||||
//读取超时时间 | //读取超时时间 | ||||
_serialPort.ReadTimeout = 500; | |||||
_serialPort.ReadTimeout = int.Parse(GetComboBoxItemValue(this.TimeOut)); | |||||
//写入超时时间 | //写入超时时间 | ||||
_serialPort.WriteTimeout = 500; | |||||
_serialPort.WriteTimeout = int.Parse(GetComboBoxItemValue(this.TimeOut)); | |||||
try | try | ||||
{ | { | ||||
_serialPort.Open(); | _serialPort.Open(); | ||||
@@ -156,14 +170,14 @@ namespace ModbusDemo.VIewModel | |||||
catch (Exception) | catch (Exception) | ||||
{ | { | ||||
MessageBox.Show("串口已经链接或者断开,请重新检查在尝试","warning",MessageBoxButton.OK,MessageBoxImage.Warning); | |||||
MessageBox.Show("串口已经链接或者断开,请重新检查在尝试", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); | |||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
MessageBox.Show("当前串口已经连接,请先断开,再连接"); | MessageBox.Show("当前串口已经连接,请先断开,再连接"); | ||||
} | } | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 处理下拉框的选择信息 | /// 处理下拉框的选择信息 | ||||
@@ -177,7 +191,7 @@ namespace ModbusDemo.VIewModel | |||||
string cleanText = displayText.Replace("System.Windows.Controls.ComboBoxItem: ", ""); | string cleanText = displayText.Replace("System.Windows.Controls.ComboBoxItem: ", ""); | ||||
return cleanText; | return cleanText; | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,3 +1,5 @@ | |||||
//using ModbusDemo.Enum; | |||||
namespace ModbusTest | namespace ModbusTest | ||||
{ | { | ||||
public class Tests | public class Tests | ||||
@@ -10,7 +12,10 @@ namespace ModbusTest | |||||
[Test] | [Test] | ||||
public void Test1() | public void Test1() | ||||
{ | { | ||||
Assert.Pass(); | |||||
byte[] byteStream = new byte[] { 0x01, 0x81, 0x01, 0x10, 0x00, 0x00, 0xAB, 0x17 }; | |||||
byte errorCodeByte = byteStream[2]; // 0x01 | |||||
//ErrorCode errorCode = (ErrorCode)errorCodeByte; // ת»»Îª ErrorCode.FunctionCodeError | |||||
//string message = errorCode.GetMessage(); | |||||
} | } | ||||
} | } | ||||
} | } |