123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- 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<WMData> 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;
- }
- /// <summary>
- /// 打开串口,并启动轮询任务
- /// </summary>
- 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}");
- }
- }
- }
- /// <summary>
- /// 轮询读取 Modbus 设备数据
- /// </summary>
- 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); // 模拟轮询间隔
- }
- }
- /// <summary>
- /// 关闭串口,并停止轮询任务
- /// </summary>
- public void StopPolling()
- {
- lock (_lock)
- {
- if (_pollingTask != null && !_pollingTask.IsCompleted)
- {
- _cancellationTokenSource?.Cancel(); // 取消任务
- try
- {
- _pollingTask.Wait(); // 等待任务结束
- }
- catch (AggregateException) { } // 忽略取消异常
- }
- _serialPort?.Close(); // 关闭串口
- _pollingTask = null;
- }
- }
- /// <summary>
- /// 写入单个寄存器,同时保证不会和轮询冲突
- /// </summary>
- 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}");
- }
- }
- }
- //--------------------------------------------------
- }
- }
|