更新
This commit is contained in:
@@ -3,11 +3,14 @@ using System.Data;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Linq;
|
||||||
using NPOI.SS.UserModel;
|
using NPOI.SS.UserModel;
|
||||||
using NPOI.XSSF.UserModel;
|
using NPOI.XSSF.UserModel;
|
||||||
using NPOI.SS.Util;
|
using NPOI.SS.Util;
|
||||||
using NPOIBorderStyle = NPOI.SS.UserModel.BorderStyle;
|
using NPOIBorderStyle = NPOI.SS.UserModel.BorderStyle;
|
||||||
using NPOIHorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment;
|
using NPOIHorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment;
|
||||||
|
using Modbus.Device;
|
||||||
|
|
||||||
namespace WindowsFormsApp6
|
namespace WindowsFormsApp6
|
||||||
{
|
{
|
||||||
@@ -17,6 +20,11 @@ namespace WindowsFormsApp6
|
|||||||
private Form2 form2Instance;
|
private Form2 form2Instance;
|
||||||
private Form3 form3Instance;
|
private Form3 form3Instance;
|
||||||
private System.Windows.Forms.Timer timeUpdateTimer;
|
private System.Windows.Forms.Timer timeUpdateTimer;
|
||||||
|
|
||||||
|
// 串口和Modbus相关
|
||||||
|
private SerialPort _serialPort;
|
||||||
|
private IModbusMaster _modbusMaster;
|
||||||
|
private System.Windows.Forms.Timer _readTimer;
|
||||||
|
|
||||||
public MainForm()
|
public MainForm()
|
||||||
{
|
{
|
||||||
@@ -24,6 +32,7 @@ namespace WindowsFormsApp6
|
|||||||
InitializeTabControl();
|
InitializeTabControl();
|
||||||
InitializeEmbeddedForms();
|
InitializeEmbeddedForms();
|
||||||
InitializeTimeUpdate();
|
InitializeTimeUpdate();
|
||||||
|
InitializeSerialPortAndModbus();
|
||||||
CenterInfoControls();
|
CenterInfoControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +49,467 @@ namespace WindowsFormsApp6
|
|||||||
timeUpdateTimer.Start();
|
timeUpdateTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化串口和Modbus通信
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeSerialPortAndModbus()
|
||||||
|
{
|
||||||
|
// 初始化读取定时器(信号量触发模式)
|
||||||
|
_readTimer = new System.Windows.Forms.Timer();
|
||||||
|
_readTimer.Interval = 100; // 100ms检查一次信号量
|
||||||
|
_readTimer.Tick += ReadTimer_Tick;
|
||||||
|
|
||||||
|
// 配置串口参数
|
||||||
|
_serialPort = new SerialPort
|
||||||
|
{
|
||||||
|
PortName = "COM2",
|
||||||
|
BaudRate = 19200,
|
||||||
|
DataBits = 8,
|
||||||
|
Parity = Parity.None,
|
||||||
|
StopBits = StopBits.One,
|
||||||
|
ReadTimeout = 500,
|
||||||
|
WriteTimeout = 500,
|
||||||
|
RtsEnable = false,
|
||||||
|
DtrEnable = false
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 打开串口
|
||||||
|
if (!_serialPort.IsOpen)
|
||||||
|
{
|
||||||
|
_serialPort.Open();
|
||||||
|
|
||||||
|
// 创建Modbus RTU主站
|
||||||
|
_modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort);
|
||||||
|
_modbusMaster.Transport.WaitToRetryMilliseconds = 200;
|
||||||
|
_modbusMaster.Transport.Retries = 1;
|
||||||
|
_modbusMaster.Transport.ReadTimeout = 500;
|
||||||
|
|
||||||
|
// 启动定时读取
|
||||||
|
_readTimer.Start();
|
||||||
|
|
||||||
|
ShowInfoMsg("数据采集器初始化成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ShowErrorMsg($"串口/Modbus初始化失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定时读取Modbus数据(信号量触发模式)
|
||||||
|
/// </summary>
|
||||||
|
private void ReadTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_modbusMaster == null || _serialPort == null || !_serialPort.IsOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte slaveId = 1; // PLC从站地址
|
||||||
|
|
||||||
|
// 读取三个信号量(M103, M252, M310)
|
||||||
|
// Modbus地址:M103 = 103, M252 = 252, M310 = 310
|
||||||
|
// 使用ReadCoils读取线圈状态(M区)
|
||||||
|
|
||||||
|
bool signalM103 = ReadCoil(slaveId, 103); // Form1信号量
|
||||||
|
bool signalM252 = ReadCoil(slaveId, 252); // Form2信号量
|
||||||
|
bool signalM310 = ReadCoil(slaveId, 310); // Form3信号量
|
||||||
|
|
||||||
|
// 根据信号量触发相应的数据读取
|
||||||
|
if (signalM103)
|
||||||
|
{
|
||||||
|
ReadForm1Data(slaveId);
|
||||||
|
// 读取完成后清除信号量
|
||||||
|
WriteCoil(slaveId, 103, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalM252)
|
||||||
|
{
|
||||||
|
ReadForm2Data(slaveId);
|
||||||
|
// 读取完成后清除信号量
|
||||||
|
WriteCoil(slaveId, 252, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalM310)
|
||||||
|
{
|
||||||
|
ReadForm3Data(slaveId);
|
||||||
|
// 读取完成后清除信号量
|
||||||
|
WriteCoil(slaveId, 310, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 读取失败时不弹窗,避免频繁打扰用户
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Modbus读取失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取单个线圈状态
|
||||||
|
/// </summary>
|
||||||
|
private bool ReadCoil(byte slaveId, ushort address)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool[] coils = _modbusMaster.ReadCoils(slaveId, address, 1);
|
||||||
|
return coils[0];
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入单个线圈状态
|
||||||
|
/// </summary>
|
||||||
|
private void WriteCoil(byte slaveId, ushort address, bool value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_modbusMaster.WriteSingleCoil(slaveId, address, value);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"写入线圈失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取Form1数据(液体吸收时间)
|
||||||
|
/// PLC地址:D200 - 时间(s)
|
||||||
|
/// 信号量:M103
|
||||||
|
/// </summary>
|
||||||
|
private void ReadForm1Data(byte slaveId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 读取D200寄存器(时间数据)
|
||||||
|
// 假设有5个试样,每个试样1个时间值
|
||||||
|
ushort[] registers = _modbusMaster.ReadHoldingRegisters(slaveId, 200, 5);
|
||||||
|
|
||||||
|
// 使用反射获取Form1的私有字段
|
||||||
|
var sampleDataTableField = form1Instance.GetType()
|
||||||
|
.GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
|
||||||
|
if (sampleDataTableField != null)
|
||||||
|
{
|
||||||
|
DataTable dataTable = sampleDataTableField.GetValue(form1Instance) as DataTable;
|
||||||
|
|
||||||
|
if (dataTable != null)
|
||||||
|
{
|
||||||
|
// 清除旧的平均值行
|
||||||
|
var avgRows = dataTable.Select("序号 = '平均时间(s)'");
|
||||||
|
foreach (var row in avgRows)
|
||||||
|
{
|
||||||
|
dataTable.Rows.Remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新数据行
|
||||||
|
DataRow dataRow = dataTable.NewRow();
|
||||||
|
dataRow["序号"] = "时间(s)";
|
||||||
|
|
||||||
|
// 填充时间数据(将寄存器值转换为实际时间,假设寄存器值为整数秒*10)
|
||||||
|
for (int i = 0; i < Math.Min(registers.Length, 5); i++)
|
||||||
|
{
|
||||||
|
double timeValue = registers[i] / 10.0; // 转换为秒
|
||||||
|
dataRow[$"试样{i + 1}"] = timeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTable.Rows.Add(dataRow);
|
||||||
|
|
||||||
|
// 计算并添加平均值行
|
||||||
|
double totalAvg = 0;
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < Math.Min(registers.Length, 5); i++)
|
||||||
|
{
|
||||||
|
totalAvg += registers[i] / 10.0;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
DataRow avgRow = dataTable.NewRow();
|
||||||
|
avgRow["序号"] = "平均时间(s)";
|
||||||
|
avgRow["试样1"] = totalAvg / count;
|
||||||
|
|
||||||
|
for (int i = 2; i <= 5; i++)
|
||||||
|
{
|
||||||
|
avgRow[$"试样{i}"] = DBNull.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTable.Rows.Add(avgRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新显示
|
||||||
|
dataTable.AcceptChanges();
|
||||||
|
this.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
// 触发Form1的界面刷新
|
||||||
|
var refreshMethod = form1Instance.GetType()
|
||||||
|
.GetMethod("RefreshDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
refreshMethod?.Invoke(form1Instance, null);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Form1数据读取成功:{registers.Length}个寄存器");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"读取Form1数据失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取Form2数据(液体吸收量)
|
||||||
|
/// PLC地址:D420 - 初始重量, D422 - 浸润后重量, D402 - 浸润时间, D406 - 悬挂时间
|
||||||
|
/// 信号量:M252
|
||||||
|
/// </summary>
|
||||||
|
private void ReadForm2Data(byte slaveId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 读取初始重量(D420开始,5个试样)
|
||||||
|
ushort[] initialWeights = _modbusMaster.ReadHoldingRegisters(slaveId, 420, 5);
|
||||||
|
|
||||||
|
// 读取浸润后重量(D422开始,5个试样)
|
||||||
|
ushort[] afterWeights = _modbusMaster.ReadHoldingRegisters(slaveId, 422, 5);
|
||||||
|
|
||||||
|
// 读取浸润时间(D402)
|
||||||
|
ushort[] soakTime = _modbusMaster.ReadHoldingRegisters(slaveId, 402, 1);
|
||||||
|
|
||||||
|
// 读取悬挂时间(D406)
|
||||||
|
ushort[] hangTime = _modbusMaster.ReadHoldingRegisters(slaveId, 406, 1);
|
||||||
|
|
||||||
|
// 使用反射获取Form2的私有字段
|
||||||
|
var sampleDataTableField = form2Instance.GetType()
|
||||||
|
.GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
|
||||||
|
if (sampleDataTableField != null)
|
||||||
|
{
|
||||||
|
DataTable dataTable = sampleDataTableField.GetValue(form2Instance) as DataTable;
|
||||||
|
|
||||||
|
if (dataTable != null)
|
||||||
|
{
|
||||||
|
dataTable.Clear();
|
||||||
|
|
||||||
|
int count = Math.Min(initialWeights.Length, 5);
|
||||||
|
|
||||||
|
// 转换数据(假设寄存器值为实际值*100)
|
||||||
|
double[] initialWeightValues = new double[count];
|
||||||
|
double[] afterWeightValues = new double[count];
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
initialWeightValues[i] = initialWeights[i] / 100.0;
|
||||||
|
afterWeightValues[i] = afterWeights[i] / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 初始重量行
|
||||||
|
DataRow initialRow = dataTable.NewRow();
|
||||||
|
initialRow["序号"] = "初始重量(g)";
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
initialRow[$"试样{i + 1}"] = initialWeightValues[i];
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(initialRow);
|
||||||
|
|
||||||
|
// 2. 浸润后重量行
|
||||||
|
DataRow afterRow = dataTable.NewRow();
|
||||||
|
afterRow["序号"] = "浸润后重量(g)";
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
afterRow[$"试样{i + 1}"] = afterWeightValues[i];
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(afterRow);
|
||||||
|
|
||||||
|
// 3. 液体吸收量行 (%)
|
||||||
|
DataRow absorptionRow = dataTable.NewRow();
|
||||||
|
absorptionRow["序号"] = "液体吸收量(%)";
|
||||||
|
double[] absorptions = new double[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
absorptions[i] = ((afterWeightValues[i] - initialWeightValues[i]) / initialWeightValues[i]) * 100;
|
||||||
|
absorptionRow[$"试样{i + 1}"] = absorptions[i];
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(absorptionRow);
|
||||||
|
|
||||||
|
// 4. 浸润时间行
|
||||||
|
DataRow soakTimeRow = dataTable.NewRow();
|
||||||
|
soakTimeRow["序号"] = "浸润时间";
|
||||||
|
for (int i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
soakTimeRow[$"试样{i}"] = $"{soakTime[0]}s";
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(soakTimeRow);
|
||||||
|
|
||||||
|
// 5. 悬挂时间行
|
||||||
|
DataRow hangTimeRow = dataTable.NewRow();
|
||||||
|
hangTimeRow["序号"] = "悬挂时间";
|
||||||
|
for (int i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
hangTimeRow[$"试样{i}"] = $"{hangTime[0]}s";
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(hangTimeRow);
|
||||||
|
|
||||||
|
// 6. 运行速度行(固定值或从其他寄存器读取)
|
||||||
|
DataRow runSpeedRow = dataTable.NewRow();
|
||||||
|
runSpeedRow["序号"] = "运行速度";
|
||||||
|
for (int i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
runSpeedRow[$"试样{i}"] = "100mm/min";
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(runSpeedRow);
|
||||||
|
|
||||||
|
// 7. 液体吸收量平均值行
|
||||||
|
DataRow avgRow = dataTable.NewRow();
|
||||||
|
avgRow["序号"] = "液体吸收量平均值(%)";
|
||||||
|
double avgAbsorption = absorptions.Average();
|
||||||
|
avgRow["试样1"] = avgAbsorption;
|
||||||
|
for (int i = 2; i <= count; i++)
|
||||||
|
{
|
||||||
|
avgRow[$"试样{i}"] = DBNull.Value;
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(avgRow);
|
||||||
|
|
||||||
|
// 8. 液体吸收量最大值行
|
||||||
|
DataRow maxRow = dataTable.NewRow();
|
||||||
|
maxRow["序号"] = "液体吸收量最大值(%)";
|
||||||
|
double maxAbsorption = absorptions.Max();
|
||||||
|
maxRow["试样1"] = maxAbsorption;
|
||||||
|
for (int i = 2; i <= count; i++)
|
||||||
|
{
|
||||||
|
maxRow[$"试样{i}"] = DBNull.Value;
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(maxRow);
|
||||||
|
|
||||||
|
// 9. 标准偏差行
|
||||||
|
DataRow stdDevRow = dataTable.NewRow();
|
||||||
|
stdDevRow["序号"] = "标准偏差";
|
||||||
|
double stdDev = CalculateStandardDeviation(absorptions);
|
||||||
|
stdDevRow["试样1"] = stdDev;
|
||||||
|
for (int i = 2; i <= count; i++)
|
||||||
|
{
|
||||||
|
stdDevRow[$"试样{i}"] = DBNull.Value;
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(stdDevRow);
|
||||||
|
|
||||||
|
// 刷新显示
|
||||||
|
dataTable.AcceptChanges();
|
||||||
|
this.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
var refreshMethod = form2Instance.GetType()
|
||||||
|
.GetMethod("RefreshDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
refreshMethod?.Invoke(form2Instance, null);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine("Form2数据读取成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"读取Form2数据失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取Form3数据(液体芯吸速率)
|
||||||
|
/// PLC地址:D456 - 吸水时间(s)
|
||||||
|
/// 信号量:M310
|
||||||
|
/// </summary>
|
||||||
|
private void ReadForm3Data(byte slaveId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 读取吸水时间(D456开始,5个试样 * 3次测试 = 15个寄存器)
|
||||||
|
ushort[] wickingTimes = _modbusMaster.ReadHoldingRegisters(slaveId, 456, 15);
|
||||||
|
|
||||||
|
// 使用反射获取Form3的私有字段
|
||||||
|
var sampleDataTableField = form3Instance.GetType()
|
||||||
|
.GetField("sampleDataTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
|
||||||
|
if (sampleDataTableField != null)
|
||||||
|
{
|
||||||
|
DataTable dataTable = sampleDataTableField.GetValue(form3Instance) as DataTable;
|
||||||
|
|
||||||
|
if (dataTable != null && dataTable.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
// 获取第一行(吸水时间行)
|
||||||
|
DataRow timeRow = dataTable.Rows[0];
|
||||||
|
|
||||||
|
// 填充吸水时间数据(假设寄存器值为实际时间*10)
|
||||||
|
int registerIndex = 0;
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
if (registerIndex < wickingTimes.Length)
|
||||||
|
{
|
||||||
|
timeRow[$"试样{i}_1"] = wickingTimes[registerIndex++] / 10.0;
|
||||||
|
}
|
||||||
|
if (registerIndex < wickingTimes.Length)
|
||||||
|
{
|
||||||
|
timeRow[$"试样{i}_2"] = wickingTimes[registerIndex++] / 10.0;
|
||||||
|
}
|
||||||
|
if (registerIndex < wickingTimes.Length)
|
||||||
|
{
|
||||||
|
timeRow[$"试样{i}_3"] = wickingTimes[registerIndex++] / 10.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用Form3的计算方法
|
||||||
|
this.Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
var calculateMethod = form3Instance.GetType()
|
||||||
|
.GetMethod("CalculateAllRows", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
calculateMethod?.Invoke(form3Instance, null);
|
||||||
|
|
||||||
|
var refreshMethod = form3Instance.GetType()
|
||||||
|
.GetMethod("RefreshDataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
refreshMethod?.Invoke(form3Instance, null);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine("Form3数据读取成功");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"读取Form3数据失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算标准偏差
|
||||||
|
/// </summary>
|
||||||
|
private double CalculateStandardDeviation(double[] values)
|
||||||
|
{
|
||||||
|
if (values == null || values.Length <= 1) return 0;
|
||||||
|
|
||||||
|
double avg = values.Average();
|
||||||
|
double sumOfSquares = values.Sum(val => Math.Pow(val - avg, 2));
|
||||||
|
return Math.Sqrt(sumOfSquares / (values.Length - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示错误消息
|
||||||
|
/// </summary>
|
||||||
|
private void ShowErrorMsg(string message)
|
||||||
|
{
|
||||||
|
MessageBox.Show(message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 显示信息消息
|
||||||
|
/// </summary>
|
||||||
|
private void ShowInfoMsg(string message)
|
||||||
|
{
|
||||||
|
MessageBox.Show(message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeTabControl()
|
private void InitializeTabControl()
|
||||||
{
|
{
|
||||||
tabControl1.SelectedIndexChanged += TabControl1_SelectedIndexChanged;
|
tabControl1.SelectedIndexChanged += TabControl1_SelectedIndexChanged;
|
||||||
@@ -830,8 +1300,29 @@ namespace WindowsFormsApp6
|
|||||||
|
|
||||||
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
|
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
|
// 停止并释放定时器
|
||||||
timeUpdateTimer?.Stop();
|
timeUpdateTimer?.Stop();
|
||||||
timeUpdateTimer?.Dispose();
|
timeUpdateTimer?.Dispose();
|
||||||
|
|
||||||
|
_readTimer?.Stop();
|
||||||
|
_readTimer?.Dispose();
|
||||||
|
|
||||||
|
// 关闭Modbus和串口
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_modbusMaster?.Dispose();
|
||||||
|
|
||||||
|
if (_serialPort != null && _serialPort.IsOpen)
|
||||||
|
{
|
||||||
|
_serialPort.Close();
|
||||||
|
}
|
||||||
|
_serialPort?.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"关闭串口失败:{ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
Application.Exit();
|
Application.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user