using Modbus.Device; using Modbus.IO; using MV485.model; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MV485.helper { public class ModbusRtuClient_p { private SerialPort _serialPort; private Task _pollingTask; private object _lock = new object(); // 互斥锁,确保轮询和写操作不会冲突 private IModbusSerialMaster _modbusMaster; //private ModbusSerialMaster _modbusMaster; private ModbusSerialTransport _modbusTransport; //private readonly byte _deviceAddress; private byte _deviceAddress; private CancellationTokenSource _cancellationTokenSource; public event Action DataReceived; // 设备数据更新事件 private byte[] sentData; //发送到设备的数据 private byte[] recvData; //从设备接收的数据 public ModbusRtuClient_p(byte deviceAddress, string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) { _deviceAddress = deviceAddress; _serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits); //_serialPort.ReadTimeout = 1000; // 设定合理的超时 //_serialPort.WriteTimeout = 1000; } /// /// 打开串口,并启动轮询任务 /// public void ConnectionLoop() { lock (_lock) // 避免多线程竞争 { StopPolling(); // 先停止之前的任务 try { if (!_serialPort.IsOpen) { _serialPort.Open(); // 打开串口 } // 在串口成功打开后创建 Modbus 主站实例 _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort); _modbusTransport = _modbusMaster.Transport; _cancellationTokenSource = new CancellationTokenSource(); _pollingTask = Task.Run(() => PollingLoop(_cancellationTokenSource.Token)); } catch (Exception ex) { Console.WriteLine($"串口打开失败: {ex.Message}"); } } } /// /// 轮询读取 Modbus 设备数据 /// private void PollingLoop(CancellationToken token) { while (!token.IsCancellationRequested) { lock (_lock) // 确保在写入寄存器时不会同时轮询 { try { if (_serialPort.IsOpen) { // 这里是读取 Modbus 数据的逻辑 Console.WriteLine("读取 Modbus 数据..."); } } catch (Exception ex) { Console.WriteLine($"PollingLoop 读取失败: {ex.Message}"); } } Thread.Sleep(1000); // 模拟轮询间隔 } } /// /// 关闭串口,并停止轮询任务 /// public void StopPolling() { lock (_lock) { if (_pollingTask != null && !_pollingTask.IsCompleted) { _cancellationTokenSource?.Cancel(); // 取消任务 try { _pollingTask.Wait(); // 等待任务结束 } catch (AggregateException) { } // 忽略取消异常 } _serialPort?.Close(); // 关闭串口 _pollingTask = null; } } /// /// 写入单个寄存器,同时保证不会和轮询冲突 /// public void WriteSingleRegister(int registerAddress, ushort value) { lock (_lock) // 确保写操作不会和轮询冲突 { try { if (_serialPort.IsOpen) { // 这里是写入 Modbus 寄存器的逻辑 Console.WriteLine($"写入寄存器 {registerAddress} 值 {value}"); } else { Console.WriteLine("串口未打开,无法写入寄存器!"); } } catch (Exception ex) { Console.WriteLine($"写入寄存器失败: {ex.Message}"); } } } //-------------------------------------------------- } }