//using Modbus.Device; using ModbusDemo.Model; using ModbusDemo.Uitls; 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 { public class AttachUCViewModel : BindableBase { private SerialPort _serialPort; public DelegateCommand ReadOddRegisterCmm { get; set; } //读取的结果 private string _readResult; public string ReadResult { get { return _readResult; } set { _readResult = value; RaisePropertyChanged(); } } //显示操作的时间 private int _time; public int Time { get { return _time; } set { _time = value; RaisePropertyChanged(); } } public AttachUCViewModel() { } public AttachUCViewModel(SerialPort serialPort) { //ReadOddRegisterCmm = new DelegateCommand(ReadOddRegister); _serialPort = serialPort; } /// /// 读1000个寄存器 /// //private void ReadOddRegister() //{ // // 创建 Modbus RTU 主站 // IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(_serialPort); // byte slaveId = 1; // ushort totalRegisters = 1000; // ushort chunkSize = 100; // int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize); // ushort[] allRegisters = new ushort[totalRegisters]; // Task[] tasks = new Task[numChunks]; // DateTime startTime = DateTime.Now; // for (int i = 0; i < numChunks; i++) // { // ushort startAddress = (ushort)(10300 + i * chunkSize); // ushort currentChunkSize = 100; // int chunkIndex = i; // tasks[i] = Task.Run(() => // { // try // { // ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, currentChunkSize); // Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); // } // catch (Exception ex) // { // MessageBox.Show($"线程 {chunkIndex} 读取寄存器时出错: {ex.Message}"); // } // }); // } // // 等待所有任务完成 // Task.WaitAll(tasks); // Time = (int)(DateTime.Now - startTime).TotalMilliseconds; // StringBuilder result = new StringBuilder(); // int count = 0; // for (int i = 1; i < totalRegisters; i += 2) // { // result.Append(allRegisters[i].ToString() + " "); // count++; // if (count % 50 == 0) // { // result.AppendLine(); // } // } // ReadResult = result.ToString(); //} /// /// 自己的类 /// private void ReadOddRegister2() { byte slaveId = 1; ushort totalRegisters = 1000; ushort chunkSize = 100; int numChunks = (int)Math.Ceiling((double)totalRegisters / chunkSize); ushort[] allRegisters = new ushort[totalRegisters]; Task[] tasks = new Task[numChunks]; DateTime startTime = DateTime.Now; for (int i = 0; i < numChunks; i++) { ushort startAddress = (ushort)(10300 + i * chunkSize); ushort currentChunkSize = 100; int chunkIndex = i; ushort[] registers = ReadRegisters(slaveId, startAddress, currentChunkSize); Array.Copy(registers, 0, allRegisters, chunkIndex * chunkSize, currentChunkSize); } // 等待所有任务完成 Time = (int)(DateTime.Now - startTime).TotalMilliseconds; StringBuilder result = new StringBuilder(); int count = 0; for (int i = 1; i < totalRegisters; i += 2) { result.Append(allRegisters[i].ToString() + " "); count++; if (count % 50 == 0) { result.AppendLine(); } } ReadResult = result.ToString(); } public ushort[] ReadRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints) { ushort[] resultValue = null; if (!_serialPort.IsOpen) { MessageBox.Show("串口没有链接,请先链接"); return resultValue; } var sendByteList = new List(8) { slaveAddress, // 从站地址 0x03, // 功能码:读保持寄存器 }; // 添加起始地址(高字节在前) sendByteList.AddRange(BitConverter.GetBytes(startAddress).Reverse()); // 添加读取点数(高字节在前) sendByteList.AddRange(BitConverter.GetBytes(numberOfPoints).Reverse()); //获取CRC校验码 byte[] getCRC = sendByteList.ToArray(); byte[] resultCRC = CRCUitl.CalculateCRC(getCRC, getCRC.Length); sendByteList.Add(resultCRC[0]); sendByteList.Add(resultCRC[1]); byte[] sendByte = sendByteList.ToArray(); int maxRetries = 3; // 最大重试次数 int attempt = 0; List responseData = new List(); byte[] response = null; while (attempt < maxRetries) { // 每次重试前清空缓冲区 responseData.Clear(); // 清除输入缓冲区残留数据 _serialPort.DiscardInBuffer(); try { _serialPort.Write(sendByte, 0, sendByte.Length); //使用时间去轮询查询数据 DateTime startTime = DateTime.Now; while ((DateTime.Now - startTime).TotalMilliseconds < _serialPort.ReadTimeout) { int bytesToRead = _serialPort.BytesToRead; if (bytesToRead > 0) { byte[] buffer = new byte[bytesToRead]; int bytesRead = _serialPort.Read(buffer, 0, bytesToRead); responseData.AddRange(buffer.Take(bytesRead)); } //延迟20毫秒,节约cpu资源 Thread.Sleep(20); } response = responseData.ToArray(); if (response.Length == 0) { continue; } resultValue = ParseRegistersresponse(sendByte, response, numberOfPoints); return resultValue; } catch (Exception) { } finally { attempt++; } } return resultValue; } /// /// 解析读取到的操作 /// /// /// /// /// public ushort[] ParseRegistersresponse(byte[] sendByte, byte[] response, ushort numberOfPoints) { //判断发送回来的数据是否正确 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]); } return registers; } else { return null; } } } }