This commit is contained in:
74
压差法气体渗透仪/NET_HRF4838_C#/Data/DataChange.cs
Normal file
74
压差法气体渗透仪/NET_HRF4838_C#/Data/DataChange.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace 薄膜气体透过率测试仪
|
||||||
|
{
|
||||||
|
public class DataChange
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ushort转为float类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="P1"></param>
|
||||||
|
/// <param name="P2"></param>
|
||||||
|
/// <returns>float型数据</returns>
|
||||||
|
public float UshortToFloat(ushort P1, ushort P2)
|
||||||
|
{
|
||||||
|
int intSign, intSignRest, intExponent, intExponentRest;
|
||||||
|
float faResult, faDigit;
|
||||||
|
intSign = P1 / 32768;
|
||||||
|
intSignRest = P1 % 32768;
|
||||||
|
intExponent = intSignRest / 128;
|
||||||
|
intExponentRest = intSignRest % 128;
|
||||||
|
faDigit = (float)(intExponentRest * 65536 + P2) / 8388608;
|
||||||
|
faResult = (float)Math.Pow(-1, intSign) * (float)Math.Pow(2, intExponent - 127) * (faDigit + 1);
|
||||||
|
return faResult;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// ushort转为int类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="u1"></param>
|
||||||
|
/// <param name="u2"></param>
|
||||||
|
/// <returns>返回int型数据</returns>
|
||||||
|
public int UshortToInt1(ushort u1, ushort u2)
|
||||||
|
{
|
||||||
|
ushort[] maidong = new ushort[2] { u1, u2 };
|
||||||
|
byte[] bytes = new byte[maidong.Length * 2];
|
||||||
|
Buffer.BlockCopy(maidong, 0, bytes, 0, bytes.Length);
|
||||||
|
int result = BitConverter.ToInt32(bytes, 0);
|
||||||
|
// 将字节数组转换为32位无符号整数
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Float转为Ushort数组发送
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns>返回ushort数组</returns>
|
||||||
|
public ushort[] SplitFloatToUShortArray(float value)
|
||||||
|
{
|
||||||
|
byte[] floatBytes = BitConverter.GetBytes(value);
|
||||||
|
ushort[] ushortArray = new ushort[floatBytes.Length / 2];
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < floatBytes.Length; i += 2, j++)
|
||||||
|
{
|
||||||
|
ushortArray[j] = BitConverter.ToUInt16(floatBytes, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ushortArray;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Int转为ushort数组发送
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="res"></param>
|
||||||
|
/// <returns>返回ushort数组</returns>
|
||||||
|
public ushort[] intToushorts(int res)
|
||||||
|
{
|
||||||
|
ushort ust1 = (ushort)(res >> 16);
|
||||||
|
ushort ust2 = (ushort)res;
|
||||||
|
return new ushort[] { ust2, ust1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
235
压差法气体渗透仪/NET_HRF4838_C#/Data/Function.cs
Normal file
235
压差法气体渗透仪/NET_HRF4838_C#/Data/Function.cs
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
using Modbus.Device;
|
||||||
|
using Modbus;
|
||||||
|
using Sunny.UI;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace 薄膜气体透过率测试仪
|
||||||
|
{
|
||||||
|
public class Function
|
||||||
|
{
|
||||||
|
ModbusMaster master;
|
||||||
|
IModbusMaster modbusMaster;
|
||||||
|
DataChange dc = new DataChange();
|
||||||
|
public enum ButtonType
|
||||||
|
{
|
||||||
|
复归型,
|
||||||
|
切换型,
|
||||||
|
置位型,
|
||||||
|
复位型
|
||||||
|
}
|
||||||
|
public enum DataType
|
||||||
|
{
|
||||||
|
整形,
|
||||||
|
浮点型
|
||||||
|
}
|
||||||
|
public Function(ModbusMaster master_in)
|
||||||
|
{
|
||||||
|
this.master = master_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function(IModbusMaster modbusMaster)
|
||||||
|
{
|
||||||
|
this.modbusMaster = modbusMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BtnClickFunction(ButtonType buttonType, ushort address)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (buttonType)
|
||||||
|
{
|
||||||
|
case ButtonType.复归型:
|
||||||
|
master.WriteSingleCoil(1, address, true);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
master.WriteSingleCoil(1, address, false);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
case ButtonType.切换型:
|
||||||
|
if (master.ReadCoils(1, address, 1)[0])
|
||||||
|
{
|
||||||
|
master.WriteSingleCoil(1, address, false); Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ master.WriteSingleCoil(1, address, true); Thread.Sleep(100); }
|
||||||
|
break;
|
||||||
|
case ButtonType.置位型:
|
||||||
|
master.WriteSingleCoil(1, address, true);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
case ButtonType.复位型:
|
||||||
|
master.WriteSingleCoil(1, address, false);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BtnClickFunctionForNew(ButtonType buttonType, ushort address)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (buttonType)
|
||||||
|
{
|
||||||
|
case ButtonType.复归型:
|
||||||
|
modbusMaster.WriteSingleCoil(1, address, true);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
modbusMaster.WriteSingleCoil(1, address, false);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
case ButtonType.切换型:
|
||||||
|
if (modbusMaster.ReadCoils(1, address, 1)[0])
|
||||||
|
{
|
||||||
|
modbusMaster.WriteSingleCoil(1, address, false); Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ modbusMaster.WriteSingleCoil(1, address, true); Thread.Sleep(100); }
|
||||||
|
break;
|
||||||
|
case ButtonType.置位型:
|
||||||
|
modbusMaster.WriteSingleCoil(1, address, true);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
case ButtonType.复位型:
|
||||||
|
modbusMaster.WriteSingleCoil(1, address, false);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void WriteToPLC(string inPutValue, ushort address, DataType dataType)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case DataType.浮点型:
|
||||||
|
double value = inPutValue.ToDouble();
|
||||||
|
if (UIInputDialog.ShowInputDoubleDialog(ref value, UIStyle.Inherited, desc: "请输入值", showMask: false))
|
||||||
|
{
|
||||||
|
|
||||||
|
master.WriteMultipleRegisters(1, address, dc.SplitFloatToUShortArray((float)value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DataType.整形:
|
||||||
|
int value_int = inPutValue.ToInt();
|
||||||
|
if (UIInputDialog.ShowInputIntegerDialog(ref value_int, UIStyle.Inherited, desc: "请输入数据:"))
|
||||||
|
{
|
||||||
|
|
||||||
|
master.WriteMultipleRegisters(1, address, dc.intToushorts(value_int));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("操作失败!" + "\n" + "\n" + ex.Message, "错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteToPLCForNew(string inPutValue, ushort address, DataType dataType, bool isok=false,float max=0,float min=0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//KeyboardHelper.ShowSoftKeyboard();
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case DataType.浮点型:
|
||||||
|
double value = inPutValue.ToDouble();
|
||||||
|
|
||||||
|
if (UIInputDialog.ShowInputDoubleDialog(ref value, UIStyle.Inherited, desc: "请输入值", showMask: false))
|
||||||
|
{
|
||||||
|
if ( isok&&value > max || value < min)
|
||||||
|
{
|
||||||
|
MessageBox.Show("数据不正确");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modbusMaster.WriteMultipleRegisters(1, address, dc.SplitFloatToUShortArray((float)value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DataType.整形:
|
||||||
|
int value_int = inPutValue.ToInt();
|
||||||
|
if (UIInputDialog.ShowInputIntegerDialog(ref value_int, UIStyle.Inherited, desc: "请输入数据:"))
|
||||||
|
{
|
||||||
|
|
||||||
|
modbusMaster.WriteMultipleRegisters(1, address, dc.intToushorts(value_int));
|
||||||
|
//if (isok)
|
||||||
|
//{ modbusMaster.WriteSingleCoil(1, 25, true); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//KeyboardHelper.HideSoftKeyboard();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("操作失败!" + "\n" + "\n" + ex.Message, "错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteToPLCForNew(string inPutValue, ushort address, DataType dataType, int d)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//KeyboardHelper.ShowSoftKeyboard();
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case DataType.浮点型:
|
||||||
|
double value = inPutValue.ToDouble();
|
||||||
|
|
||||||
|
if (UIInputDialog.ShowInputDoubleDialog(ref value, UIStyle.Inherited, d, desc: "请输入值", showMask: false))
|
||||||
|
{
|
||||||
|
|
||||||
|
modbusMaster.WriteMultipleRegisters(1, address, dc.SplitFloatToUShortArray((float)value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DataType.整形:
|
||||||
|
int value_int = inPutValue.ToInt();
|
||||||
|
if (UIInputDialog.ShowInputIntegerDialog(ref value_int, UIStyle.Inherited, desc: "请输入数据:"))
|
||||||
|
{
|
||||||
|
|
||||||
|
modbusMaster.WriteMultipleRegisters(1, address, dc.intToushorts(value_int));
|
||||||
|
//if (isok)
|
||||||
|
//{ modbusMaster.WriteSingleCoil(1, 25, true); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//KeyboardHelper.HideSoftKeyboard();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("操作失败!" + "\n" + "\n" + ex.Message, "错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
69
压差法气体渗透仪/NET_HRF4838_C#/Data/ModbusResourceManager.cs
Normal file
69
压差法气体渗透仪/NET_HRF4838_C#/Data/ModbusResourceManager.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using Modbus.Device;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace 薄膜气体透过率测试仪.Data
|
||||||
|
{
|
||||||
|
// 单例模式:全局唯一资源管理器
|
||||||
|
public class ModbusResourceManager
|
||||||
|
{
|
||||||
|
// 私有构造函数:禁止外部new
|
||||||
|
private ModbusResourceManager() { }
|
||||||
|
|
||||||
|
// 唯一实例
|
||||||
|
private static readonly Lazy<ModbusResourceManager> _instance = new Lazy<ModbusResourceManager>(() => new ModbusResourceManager());
|
||||||
|
public static ModbusResourceManager Instance => _instance.Value;
|
||||||
|
|
||||||
|
// 共享资源
|
||||||
|
public TcpClient TcpClient { get; private set; }
|
||||||
|
public IModbusMaster ModbusMaster { get; private set; }
|
||||||
|
|
||||||
|
// 初始化资源(在程序启动时调用,如MainWindow加载时)
|
||||||
|
public bool Init(string ip, int port)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 先释放旧资源
|
||||||
|
ReleaseResource();
|
||||||
|
|
||||||
|
// 创建新连接
|
||||||
|
TcpClient = new TcpClient();
|
||||||
|
TcpClient.Connect(ip, port);
|
||||||
|
ModbusMaster = ModbusIpMaster.CreateIp(TcpClient);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"资源初始化失败:{ex.Message}");
|
||||||
|
ReleaseResource();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ModbusMaster?.Dispose();
|
||||||
|
TcpClient?.Close();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 忽略清理时的异常
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 释放资源(统一释放,避免重复关闭)
|
||||||
|
public void ReleaseResource()
|
||||||
|
{
|
||||||
|
ModbusMaster?.Dispose();
|
||||||
|
ModbusMaster = null;
|
||||||
|
|
||||||
|
//if (TcpClient?.Connected ?? false)
|
||||||
|
//{
|
||||||
|
// TcpClient.Close();
|
||||||
|
//}
|
||||||
|
TcpClient?.Dispose();
|
||||||
|
TcpClient = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,37 @@
|
|||||||
using System;
|
using Modbus.Device;
|
||||||
|
using Sunny.UI;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows.Forms.DataVisualization.Charting;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using Sunny.UI;
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Forms.DataVisualization.Charting;
|
||||||
|
using 薄膜气体透过率测试仪;
|
||||||
|
using 薄膜气体透过率测试仪.Data;
|
||||||
//新
|
//新
|
||||||
namespace NET_HRF4826
|
namespace NET_HRF4826
|
||||||
{
|
{
|
||||||
public partial class Form1 : UIForm
|
public partial class Form1 : UIForm
|
||||||
{
|
{
|
||||||
|
private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
|
||||||
|
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
|
||||||
|
|
||||||
|
Function ma;
|
||||||
|
DataChange c = new DataChange();
|
||||||
|
private System.Windows.Forms.Timer _readtimer;
|
||||||
|
System.Windows.Forms.Timer Timer;
|
||||||
|
|
||||||
|
private int smoothWindow = 100; // 平滑窗口大小,可根据需要调整
|
||||||
Thread threadReceiveData = new Thread(ReceiveData);
|
Thread threadReceiveData = new Thread(ReceiveData);
|
||||||
static int waitbytes = 7000;
|
static int waitbytes = 7000;
|
||||||
UInt16 temp;
|
UInt16 temp;
|
||||||
@@ -65,12 +78,140 @@ namespace NET_HRF4826
|
|||||||
|
|
||||||
// 新增:是否已开始记录有效数据
|
// 新增:是否已开始记录有效数据
|
||||||
private bool hasValidDataStarted = false;
|
private bool hasValidDataStarted = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 存储从PLC读取的最新压力值(单位Pa)
|
||||||
|
private float? _plcLowPressurePa;
|
||||||
|
private float? _plcHighPressurePa;
|
||||||
|
private readonly object _plcPressureLock = new object();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Form1()
|
public Form1()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private System.Windows.Forms.Timer InitTimer()
|
||||||
|
{
|
||||||
|
var timer = new System.Windows.Forms.Timer()
|
||||||
|
{
|
||||||
|
Interval = 80,
|
||||||
|
};
|
||||||
|
timer.Tick += async (s, e) =>
|
||||||
|
{
|
||||||
|
if (_modbusMaster != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ReadDataAsync();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return timer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async System.Threading.Tasks.Task ReadDataAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_modbusMaster == null || _tcpClient == null || !_tcpClient.Connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 高压:使用ReadFloatAsync读取浮点数
|
||||||
|
var highPressureTask = ReadFloatAsync(1034, 2);
|
||||||
|
|
||||||
|
// 低压:使用ReadDWordAsync读取32位整数
|
||||||
|
var lowPressureTask = ReadDWordAsync(1140, null); // 低压地址假设为1140,请确认实际地址
|
||||||
|
|
||||||
|
await Task.WhenAll(highPressureTask, lowPressureTask);
|
||||||
|
|
||||||
|
// 更新高压字段(单位假设为Pa)
|
||||||
|
if (highPressureTask.Result.HasValue)
|
||||||
|
{
|
||||||
|
lock (_plcPressureLock)
|
||||||
|
_plcHighPressurePa = highPressureTask.Result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新低压字段(从DWord读取的整数值,假设单位已经是Pa)
|
||||||
|
if (lowPressureTask.Result.HasValue)
|
||||||
|
{
|
||||||
|
lock (_plcPressureLock)
|
||||||
|
_plcLowPressurePa = lowPressureTask.Result.Value; // 直接使用整数值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_readtimer?.Stop();
|
||||||
|
Timer?.Stop();
|
||||||
|
System.Diagnostics.Debug.WriteLine($"读取数据失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<float?> ReadFloatAsync(int address, int length)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ushort[] registers = await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (_modbusMaster == null) return null;
|
||||||
|
return await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)address, (ushort)length);
|
||||||
|
});
|
||||||
|
if (registers != null && registers.Length >= 2)
|
||||||
|
{
|
||||||
|
return c.UshortToFloat(registers[1], registers[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<int?> ReadDWordAsync(int startAddress, Label control, string format = "D", string unit = "")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 32位 DWord 占用 2 个连续寄存器
|
||||||
|
ushort[] registers = await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (_modbusMaster == null) return null;
|
||||||
|
return await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)startAddress, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (registers != null && registers.Length >= 2)
|
||||||
|
{
|
||||||
|
// 将两个16位寄存器组合成32位有符号整数
|
||||||
|
// 注意寄存器顺序:通常是 低16位在前(D1140),高16位在后(D1141)
|
||||||
|
int value = (registers[1] << 16) | registers[0];
|
||||||
|
|
||||||
|
// 如果提供了control,则更新UI
|
||||||
|
if (control != null && !control.IsDisposed)
|
||||||
|
{
|
||||||
|
control.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
control.Text = value.ToString() + unit;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"读取DWord地址{startAddress}失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void Read_Data()
|
private void Read_Data()
|
||||||
{
|
{
|
||||||
// ★ 关键修复:复制 readdata 到本地缓冲区,避免被后台线程修改
|
// ★ 关键修复:复制 readdata 到本地缓冲区,避免被后台线程修改
|
||||||
@@ -171,7 +312,7 @@ namespace NET_HRF4826
|
|||||||
if (shouldRecord)
|
if (shouldRecord)
|
||||||
{
|
{
|
||||||
if (!hasValidDataStarted) hasValidDataStarted = true;
|
if (!hasValidDataStarted) hasValidDataStarted = true;
|
||||||
// 记录当前采样点
|
|
||||||
var record = new DataRecord
|
var record = new DataRecord
|
||||||
{
|
{
|
||||||
Timestamp = DateTime.Now,
|
Timestamp = DateTime.Now,
|
||||||
@@ -185,11 +326,17 @@ namespace NET_HRF4826
|
|||||||
Frequency = new uint[] { frequency0, frequency1, frequency2 }
|
Frequency = new uint[] { frequency0, frequency1, frequency2 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 从PLC字段获取当前压力值(单位Pa)
|
||||||
|
lock (_plcPressureLock)
|
||||||
|
{
|
||||||
|
record.LowPressureCalibrated = _plcLowPressurePa.HasValue ? (float)_plcLowPressurePa.Value : 0f;
|
||||||
|
record.HighPressureCalibrated = _plcHighPressurePa ?? 0f;
|
||||||
|
}
|
||||||
|
|
||||||
lock (dataLock)
|
lock (dataLock)
|
||||||
{
|
{
|
||||||
allDataRecords.Add(record);
|
allDataRecords.Add(record);
|
||||||
totalRecordsAdded++;
|
totalRecordsAdded++;
|
||||||
// 调试输出(每1000条一次)
|
|
||||||
if (totalRecordsAdded % 1000 == 0)
|
if (totalRecordsAdded % 1000 == 0)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"已添加 {totalRecordsAdded} 条记录,AI0电压={volt[i, 0]:F4}V");
|
System.Diagnostics.Debug.WriteLine($"已添加 {totalRecordsAdded} 条记录,AI0电压={volt[i, 0]:F4}V");
|
||||||
@@ -206,21 +353,32 @@ namespace NET_HRF4826
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新UI(使用第一个采样点的数据)
|
|
||||||
// AI0 压力转换(0 ~ 100 kPa)
|
|
||||||
double pressure0 = volt[0, 0] * 10.0;
|
|
||||||
AI0_textBox.Text = pressure0.ToString("f3") + " kPa";
|
|
||||||
|
|
||||||
// AI1 压力转换(0 ~ 600 kPa)
|
|
||||||
double pressure1 = volt[0, 1] * 60.0;
|
//// 更新UI(使用第一个采样点的数据)
|
||||||
AI1_textBox.Text = pressure1.ToString("f3") + " kPa";
|
//// AI0 压力转换(0 ~ 100 kPa)
|
||||||
|
//double pressure0 = volt[0, 0] * 10.0;
|
||||||
|
//AI0_textBox.Text = pressure0.ToString("f3") + " kPa";
|
||||||
|
|
||||||
|
//// AI1 压力转换(0 ~ 600 kPa)
|
||||||
|
//double pressure1 = volt[0, 1] * 60.0;
|
||||||
|
//AI1_textBox.Text = pressure1.ToString("f3") + " kPa";
|
||||||
|
|
||||||
|
|
||||||
|
lock (_plcPressureLock)
|
||||||
|
{
|
||||||
|
if (_plcLowPressurePa.HasValue)
|
||||||
|
AI0_textBox.Text = _plcLowPressurePa.Value.ToString("F1") + " Pa";
|
||||||
|
if (_plcHighPressurePa.HasValue)
|
||||||
|
AI1_textBox.Text = _plcHighPressurePa.Value.ToString("F1") + " kPa";
|
||||||
|
}
|
||||||
|
|
||||||
// 更新DI按钮状态(使用第一个采样点)
|
// 更新DI按钮状态(使用第一个采样点)
|
||||||
DI0 = dat[0, 32];
|
DI0 = dat[0, 32];
|
||||||
DI1 = dat[0, 33];
|
DI1 = dat[0, 33];
|
||||||
DI2 = dat[0, 34];
|
DI2 = dat[0, 34];
|
||||||
DI3 = dat[0, 35];
|
DI3 = dat[0, 35];
|
||||||
// ... DI按钮更新代码(略,保持原样)...
|
|
||||||
|
|
||||||
// 更新脉冲计数和频率文本框
|
// 更新脉冲计数和频率文本框
|
||||||
PulseCount0_textBox.Text = Convert.ToUInt32((dat[0, 51] << 24) + (dat[0, 50] << 16) + (dat[0, 49] << 8) + dat[0, 48]).ToString();
|
PulseCount0_textBox.Text = Convert.ToUInt32((dat[0, 51] << 24) + (dat[0, 50] << 16) + (dat[0, 49] << 8) + dat[0, 48]).ToString();
|
||||||
@@ -705,6 +863,36 @@ namespace NET_HRF4826
|
|||||||
Y = this.Height;//获取窗体的高度
|
Y = this.Height;//获取窗体的高度
|
||||||
setTag(this);//调用方法
|
setTag(this);//调用方法
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
string plcIp = "192.168.1.10";
|
||||||
|
//string plcIp = "127.0.0.1";
|
||||||
|
bool initSuccess = ModbusResourceManager.Instance.Init(plcIp, 502);
|
||||||
|
if (!initSuccess)
|
||||||
|
{
|
||||||
|
MessageBox.Show("连接Modbus服务器失败!", "错误");
|
||||||
|
this.Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查连接状态
|
||||||
|
if (_tcpClient == null || !_tcpClient.Connected)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Modbus连接异常!", "错误");
|
||||||
|
this.Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ma = new Function(_modbusMaster);
|
||||||
|
|
||||||
|
_readtimer = InitTimer();
|
||||||
|
if (_modbusMaster != null)
|
||||||
|
{
|
||||||
|
_readtimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float X;//当前窗体的宽度
|
private float X;//当前窗体的宽度
|
||||||
@@ -785,8 +973,8 @@ namespace NET_HRF4826
|
|||||||
{
|
{
|
||||||
// 写入表头
|
// 写入表头
|
||||||
var header = new List<string> { "序号", "时间" };
|
var header = new List<string> { "序号", "时间" };
|
||||||
header.Add("低压(kPa)"); // AI0:0~100 kPa
|
header.Add("低压(Pa)"); // AI0
|
||||||
header.Add("高压(kPa)"); // AI1:0~600 kPa
|
header.Add("高压(kPa)"); // AI1
|
||||||
for (int i = 2; i < 16; i++) header.Add($"AI{i}(V)");
|
for (int i = 2; i < 16; i++) header.Add($"AI{i}(V)");
|
||||||
for (int i = 0; i < 32; i++) header.Add($"DI{i}");
|
for (int i = 0; i < 32; i++) header.Add($"DI{i}");
|
||||||
for (int i = 0; i < 3; i++) header.Add($"PulseCount{i}");
|
for (int i = 0; i < 3; i++) header.Add($"PulseCount{i}");
|
||||||
@@ -806,17 +994,15 @@ namespace NET_HRF4826
|
|||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
// AI0:0~100 kPa(与界面一致)
|
// 使用校准后的低压(Pa)
|
||||||
double pressure0 = record.AI[i] * 10.0;
|
row.Add(record.LowPressureCalibrated.ToString("F1"));
|
||||||
row.Add(pressure0.ToString("F3"));
|
|
||||||
if (rowCount < 10)
|
if (rowCount < 10)
|
||||||
System.Diagnostics.Debug.WriteLine($"记录{rowCount}: 索引={record.SampleIndex}, AI0电压={record.AI[i]:F4}V → 压力={pressure0:F3}kPa");
|
System.Diagnostics.Debug.WriteLine($"记录{rowCount}: 低压校准值={record.LowPressureCalibrated:F1}Pa");
|
||||||
}
|
}
|
||||||
else if (i == 1)
|
else if (i == 1)
|
||||||
{
|
{
|
||||||
// AI1:0~600 kPa
|
// 使用校准后的高压(Pa)
|
||||||
double pressure1 = record.AI[i] * 60.0;
|
row.Add(record.HighPressureCalibrated.ToString("F1"));
|
||||||
row.Add(pressure1.ToString("F3"));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -855,5 +1041,8 @@ namespace NET_HRF4826
|
|||||||
public byte[] DI { get; set; } = new byte[4]; // 4个字节的DI状态(共32位)
|
public byte[] DI { get; set; } = new byte[4]; // 4个字节的DI状态(共32位)
|
||||||
public uint[] PulseCount { get; set; } = new uint[3]; // 3个脉冲计数器
|
public uint[] PulseCount { get; set; } = new uint[3]; // 3个脉冲计数器
|
||||||
public uint[] Frequency { get; set; } = new uint[3]; // 3个频率值
|
public uint[] Frequency { get; set; } = new uint[3]; // 3个频率值
|
||||||
|
|
||||||
|
public float LowPressureCalibrated { get; set; } // 低压校准值(Pa)
|
||||||
|
public float HighPressureCalibrated { get; set; } // 高压校准值(Pa)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,6 +58,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.VisualBasic" />
|
<Reference Include="Microsoft.VisualBasic" />
|
||||||
<Reference Include="Microsoft.VisualBasic.PowerPacks.Vs, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
<Reference Include="Microsoft.VisualBasic.PowerPacks.Vs, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="NModbus4, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\NModbus4.2.1.0\lib\net40\NModbus4.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="SunnyUI, Version=3.8.9.0, Culture=neutral, PublicKeyToken=27d7d2e821d97aeb, processorArchitecture=MSIL">
|
<Reference Include="SunnyUI, Version=3.8.9.0, Culture=neutral, PublicKeyToken=27d7d2e821d97aeb, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\SunnyUI.3.8.9\lib\net472\SunnyUI.dll</HintPath>
|
<HintPath>..\..\packages\SunnyUI.3.8.9\lib\net472\SunnyUI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -79,6 +85,9 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Data\DataChange.cs" />
|
||||||
|
<Compile Include="Data\Function.cs" />
|
||||||
|
<Compile Include="Data\ModbusResourceManager.cs" />
|
||||||
<Compile Include="Form1.cs">
|
<Compile Include="Form1.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net48" />
|
||||||
|
<package id="NModbus4" version="2.1.0" targetFramework="net48" />
|
||||||
<package id="SunnyUI" version="3.8.9" targetFramework="net48" />
|
<package id="SunnyUI" version="3.8.9" targetFramework="net48" />
|
||||||
<package id="SunnyUI.Common" version="3.8.9" targetFramework="net48" />
|
<package id="SunnyUI.Common" version="3.8.9" targetFramework="net48" />
|
||||||
</packages>
|
</packages>
|
||||||
Reference in New Issue
Block a user