diff --git a/ModbusDemo/Device/ModbusRTU.cs b/ModbusDemo/Device/ModbusRTU.cs index 7f669e4..f578025 100644 --- a/ModbusDemo/Device/ModbusRTU.cs +++ b/ModbusDemo/Device/ModbusRTU.cs @@ -147,7 +147,7 @@ namespace ModbusDemo.Device } - + } /// /// 写入多个线圈操作 @@ -160,7 +160,7 @@ namespace ModbusDemo.Device if (!_serialPort.IsOpen) { MessageBox.Show("串口没有链接,请先链接"); - return ; + return; } List sendByteList = new List(); //设置从站地址 @@ -205,12 +205,10 @@ namespace ModbusDemo.Device byte[] response = null; while (attempt < maxRetries) { - try { // 清空接收缓冲区(避免残留数据干扰) _serialPort.DiscardInBuffer(); - _serialPort.Write(sendByte, 0, sendByte.Length); Thread.Sleep(300); response = new byte[_serialPort.BytesToRead]; @@ -219,7 +217,6 @@ namespace ModbusDemo.Device { break; } - } catch (Exception) { @@ -241,21 +238,18 @@ namespace ModbusDemo.Device //判断发送回来的数据是否正确 if (CheckData.CheckResponse(response)) { - if (!CRCUitl.ValidateCRC(response)) - { - MessageBox.Show("0x14:CRC校验错误"); - } - + } - + } public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) { + ushort[] resultValue = null; if (!_serialPort.IsOpen) { MessageBox.Show("串口没有链接,请先链接"); - return null; + return resultValue; } List sendByteList = new List(); //设置从站地址 @@ -275,19 +269,46 @@ namespace ModbusDemo.Device sendByteList.Add(resultCRC[1]); byte[] sendByte = sendByteList.ToArray(); - if (_serialPort.IsOpen) + int maxRetries = 3; // 最大重试次数 + int attempt = 0; + while (attempt < maxRetries) { - // 清空接收缓冲区(避免残留数据干扰) - _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(sendByte, response, numberOfPoints); + try + { + // 清空接收缓冲区(避免残留数据干扰) + _serialPort.DiscardInBuffer(); + + _serialPort.Write(sendByte, 0, sendByte.Length); + Thread.Sleep(300); + byte[] response = new byte[_serialPort.BytesToRead]; + _serialPort.Read(response, 0, _serialPort.BytesToRead); + if (response[0] == 0x00) + { + continue; + } + resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); + return resultValue; + } + catch (Exception) + { + + attempt++; + } + } + //将操作失败的指令,插入数据库 + string RequestStr = ByteArrayToString(sendByte); + + ModbusLog m = new ModbusLog(); + m.OperationType = "读寄存器"; + m.ResponseData = ""; + m.RequestData = RequestStr; + _modbusDbContext.Add(m); + _modbusDbContext.SaveChanges(); + return resultValue; + + - return null; } public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) { @@ -302,27 +323,35 @@ namespace ModbusDemo.Device _modbusDbContext.SaveChanges(); //判断发送回来的数据是否正确 - CheckData.CheckResponse(response); + if (CheckData.CheckResponse(response)) + { + 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]); + } - if (!CRCUitl.ValidateCRC(response)) + return registers; + } + else { - 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; + + } public void WriteRegisters(byte slaveAddress, ushort startAddress, ushort[] data) { + if (!_serialPort.IsOpen) + { + MessageBox.Show("串口没有链接,请先链接"); + return; + } List sendByteList = new List(); //设置从站地址 sendByteList.Add(slaveAddress); @@ -353,39 +382,52 @@ namespace ModbusDemo.Device sendByteList.Add(resultCRC[0]); sendByteList.Add(resultCRC[1]); - byte[] sendByte = sendByteList.ToArray(); - if (_serialPort.IsOpen) + + + int maxRetries = 3; // 最大重试次数 + int attempt = 0; + byte[] response = null; + + while (attempt< maxRetries) { - // 清空接收缓冲区(避免残留数据干扰) - _serialPort.DiscardInBuffer(); - - _serialPort.Write(sendByte, 0, sendByte.Length); - Thread.Sleep(300); - byte[] response = new byte[_serialPort.BytesToRead]; - _serialPort.Read(response, 0, _serialPort.BytesToRead); - - //将操作的指令,插入数据库 - string RequestStr = ByteArrayToString(sendByte); - string responseStr = ByteArrayToString(response); - ModbusLog m = new ModbusLog(); - m.OperationType = "写寄存器"; - m.ResponseData = responseStr; - m.RequestData = responseStr; - _modbusDbContext.Add(m); - _modbusDbContext.SaveChanges(); - - //判断发送回来的数据是否正确 - CheckData.CheckResponse(response); - - if (!CRCUitl.ValidateCRC(response)) + try { - MessageBox.Show("0x14:CRC校验错误"); + // 清空接收缓冲区(避免残留数据干扰) + _serialPort.DiscardInBuffer(); + _serialPort.Write(sendByte, 0, sendByte.Length); + Thread.Sleep(1000); + response = new byte[_serialPort.BytesToRead]; + _serialPort.Read(response, 0, _serialPort.BytesToRead); + if (response[0] != 0x00) + { + break; + } + } + catch (Exception) + { + attempt++; } } + + //将操作的指令,插入数据库 + string RequestStr = ByteArrayToString(sendByte); + string responseStr = ByteArrayToString(response); + ModbusLog m = new ModbusLog(); + m.OperationType = "写寄存器"; + m.ResponseData = responseStr; + m.RequestData = responseStr; + _modbusDbContext.Add(m); + _modbusDbContext.SaveChanges(); + + //判断发送回来的数据是否正确 + CheckData.CheckResponse(response); + + } + static string ByteArrayToString(byte[] byteArray) { if (byteArray == null || byteArray.Length == 0) diff --git a/ModbusDemo/VIewModel/CoilUCViewModel.cs b/ModbusDemo/VIewModel/CoilUCViewModel.cs index b031a5a..48e5ee5 100644 --- a/ModbusDemo/VIewModel/CoilUCViewModel.cs +++ b/ModbusDemo/VIewModel/CoilUCViewModel.cs @@ -250,7 +250,7 @@ namespace ModbusDemo.VIewModel } else { - MessageBox.Show("WriteData 格式无效", "error", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show("写入失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); } }); diff --git a/ModbusDemo/VIewModel/RegisterUCViewModel.cs b/ModbusDemo/VIewModel/RegisterUCViewModel.cs index 623a469..7d5efe2 100644 --- a/ModbusDemo/VIewModel/RegisterUCViewModel.cs +++ b/ModbusDemo/VIewModel/RegisterUCViewModel.cs @@ -12,7 +12,7 @@ using System.Windows; namespace ModbusDemo.VIewModel { - class RegisterUCViewModel:BindableBase + class RegisterUCViewModel : BindableBase { //定义数据库操作类 private ModbusDbContext _modbusDbContext; @@ -147,9 +147,9 @@ namespace ModbusDemo.VIewModel public RegisterUCViewModel() { - + } - public RegisterUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU,ModbusDbContext modbusDbContext) + public RegisterUCViewModel(SerialPort serialPort, ModbusRTU modbusRTU, ModbusDbContext modbusDbContext) { _serialPort = serialPort; ReadRegisterCmm = new DelegateCommand(ReadRegister); @@ -161,7 +161,7 @@ namespace ModbusDemo.VIewModel } - + /// @@ -169,31 +169,65 @@ namespace ModbusDemo.VIewModel /// private void ReadRegister() { - try + if (!byte.TryParse(SlaveAddress, out byte slaveAddressValue)) { - 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; - } + MessageBox.Show("SlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; } - catch (Exception) + + if (!ushort.TryParse(StartAddress, out ushort startAddressValue)) { + MessageBox.Show("StartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } - MessageBox.Show("参数配置错误"); + if (!ushort.TryParse(NumberOfPoints, out ushort numberOfPointsValue)) + { + MessageBox.Show("NumberOfPoints 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; } + //使用子线程进行读取,防止ui线程卡顿 + Task.Run(() => + { + ushort[] result = _modbusRTU.ReadRegisters(slaveAddressValue, startAddressValue, numberOfPointsValue); + if (result == null) + { + MessageBox.Show("读取失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); + ModbusLogList = GetOperateRegister(); + return; + } + string temp = ""; + foreach (var item in result) + { + temp += item; + temp += " "; + } + ReadResult = temp; + MessageBox.Show("读取成功"); + ModbusLogList = GetOperateRegister(); + }); } + + + private void WriteRegister() { + if (!byte.TryParse(WriteSlaveAddress, out byte writeSlaveAddressValue)) + { + MessageBox.Show("WriteSlaveAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + if (!ushort.TryParse(WriteStartAddress, out ushort WriteStartAddressValue)) + { + MessageBox.Show("WriteStartAddress 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + if (string.IsNullOrEmpty(WriteData)) + { + MessageBox.Show("WriteData 格式无效", "warning", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } string[] parts = WriteData.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // 3. 创建结果数组 ushort[] data = new ushort[parts.Length]; @@ -208,22 +242,31 @@ namespace ModbusDemo.VIewModel } else { - // 处理解析失败的情况 - throw new FormatException($"无法将 '{parts[i]}' 转换为 ushort 类型"); + + MessageBox.Show($"无法将 '{parts[i]}' 转换为 ushort 类型"); + return; } } - try - { - _modbusRTU.WriteRegisters(byte.Parse(WriteSlaveAddress), - ushort.Parse(WriteStartAddress), - data); - } - catch (Exception) + //使用子线程来去执行操作,防止ui线程卡顿 + Task.Run(() => { + _modbusRTU.WriteRegisters(writeSlaveAddressValue, WriteStartAddressValue, data); + ModbusLogList = GetOperateRegister(); + ModbusLog modbusLog = ModbusLogList.FirstOrDefault(); + if (modbusLog != null && modbusLog.ResponseData != string.Empty) + { + MessageBox.Show("写入成功"); + + } + else + { + MessageBox.Show("写入失败", "error", MessageBoxButton.OK, MessageBoxImage.Error); + } + }); + + - MessageBox.Show("信息配置错误"); - } } ///