This commit is contained in:
@@ -73,18 +73,34 @@
|
||||
<StackPanel Grid.Row="0" Grid.Column="0" Margin="5">
|
||||
<TextBlock Text="第1次" FontWeight="Bold"/>
|
||||
<TextBox x:Name="txtTime1" Width="80" Margin="0,2"/>
|
||||
<WrapPanel HorizontalAlignment="Center" Margin="0,2">
|
||||
<Button x:Name="btnStart1" Content="开始" Width="35" Height="20" FontSize="10" Click="BtnStart1_Click"/>
|
||||
<Button x:Name="btnStop1" Content="结束" Width="35" Height="20" FontSize="10" Click="BtnStop1_Click" Margin="5,0,0,0"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" Margin="5">
|
||||
<TextBlock Text="第2次" FontWeight="Bold"/>
|
||||
<TextBox x:Name="txtTime2" Width="80" Margin="0,2"/>
|
||||
<WrapPanel HorizontalAlignment="Center" Margin="0,2">
|
||||
<Button x:Name="btnStart2" Content="开始" Width="35" Height="20" FontSize="10" Click="BtnStart2_Click"/>
|
||||
<Button x:Name="btnStop2" Content="结束" Width="35" Height="20" FontSize="10" Click="BtnStop2_Click" Margin="5,0,0,0"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="2" Margin="5">
|
||||
<TextBlock Text="第3次" FontWeight="Bold"/>
|
||||
<TextBox x:Name="txtTime3" Width="80" Margin="0,2"/>
|
||||
<WrapPanel HorizontalAlignment="Center" Margin="0,2">
|
||||
<Button x:Name="btnStart3" Content="开始" Width="35" Height="20" FontSize="10" Click="BtnStart3_Click"/>
|
||||
<Button x:Name="btnStop3" Content="结束" Width="35" Height="20" FontSize="10" Click="BtnStop3_Click" Margin="5,0,0,0"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="3" Margin="5">
|
||||
<TextBlock Text="第4次" FontWeight="Bold"/>
|
||||
<TextBox x:Name="txtTime4" Width="80" Margin="0,2"/>
|
||||
<WrapPanel HorizontalAlignment="Center" Margin="0,2">
|
||||
<Button x:Name="btnStart4" Content="开始" Width="35" Height="20" FontSize="10" Click="BtnStart4_Click"/>
|
||||
<Button x:Name="btnStop4" Content="结束" Width="35" Height="20" FontSize="10" Click="BtnStop4_Click" Margin="5,0,0,0"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第二行:更多时间输入(支持最多6次) -->
|
||||
|
||||
@@ -3,7 +3,9 @@ using PetroleumViscosityTest.Controls;
|
||||
using PetroleumViscosityTest.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
@@ -13,6 +15,18 @@ namespace PetroleumViscosityTest
|
||||
{
|
||||
private ViscosityTestData currentData;
|
||||
private List<double> rawTimes = new List<double>();
|
||||
// --- 新增 Modbus 通信相关字段 ---
|
||||
private SerialPort serialPort;
|
||||
private System.Timers.Timer readTimer;
|
||||
private byte slaveId = 0x01; // 从机地址,根据实际修改
|
||||
private readonly object portLock = new object();
|
||||
|
||||
|
||||
private System.Diagnostics.Stopwatch stopwatch1 = new System.Diagnostics.Stopwatch();
|
||||
private System.Diagnostics.Stopwatch stopwatch2 = new System.Diagnostics.Stopwatch();
|
||||
private System.Diagnostics.Stopwatch stopwatch3 = new System.Diagnostics.Stopwatch();
|
||||
private System.Diagnostics.Stopwatch stopwatch4 = new System.Diagnostics.Stopwatch();
|
||||
// --------------------------------
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
@@ -20,7 +34,218 @@ namespace PetroleumViscosityTest
|
||||
currentData = new ViscosityTestData();
|
||||
dpTestDate.SelectedDate = DateTime.Today;
|
||||
UpdateThermostatTime();
|
||||
|
||||
// --- 新增:初始化串口通信 ---
|
||||
InitSerialPort();
|
||||
// --------------------------------
|
||||
}
|
||||
|
||||
private void InitSerialPort()
|
||||
{
|
||||
try
|
||||
{
|
||||
serialPort = new SerialPort("COM6", 9600, Parity.None, 8, StopBits.One); // 请根据实际COM口修改
|
||||
serialPort.DataReceived += SerialPort_DataReceived;
|
||||
serialPort.Open();
|
||||
|
||||
// 启动定时器,每隔 5 秒读取一次
|
||||
readTimer = new System.Timers.Timer(2000);
|
||||
readTimer.Elapsed += ReadTimer_Elapsed;
|
||||
readTimer.AutoReset = true;
|
||||
readTimer.Start();
|
||||
|
||||
txtStatus.Text = "串口已打开,正在读取数据...";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"串口打开失败: {ex.Message}\n请检查COM口号及连接。", "通信错误", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
txtStatus.Text = "串口打开失败";
|
||||
}
|
||||
}
|
||||
|
||||
//private void ReadTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
//{
|
||||
// // 发送读保持寄存器指令:功能码 0x03,起始地址 0x0005,读取 2 个寄存器
|
||||
// byte[] request = new byte[8];
|
||||
// request[0] = slaveId;
|
||||
// request[1] = 0x03; // 功能码
|
||||
// request[2] = 0x00; // 起始地址高字节
|
||||
// request[3] = 0x05; // 起始地址低字节 (0x0005)
|
||||
// request[4] = 0x00; // 数量高字节
|
||||
// request[5] = 0x02; // 数量低字节 (2 个寄存器)
|
||||
// byte[] crc = CalculateCRC16(request, 6);
|
||||
// request[6] = crc[0];
|
||||
// request[7] = crc[1];
|
||||
|
||||
// lock (portLock)
|
||||
// {
|
||||
// if (serialPort != null && serialPort.IsOpen)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// serialPort.Write(request, 0, request.Length);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Dispatcher.Invoke(() => txtStatus.Text = $"发送失败: {ex.Message}");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
// 替换原有的 ReadTimer_Elapsed 方法
|
||||
private void ReadTimer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
lock (portLock)
|
||||
{
|
||||
if (serialPort == null || !serialPort.IsOpen) return;
|
||||
|
||||
// 从 0x0000 开始读取 20 个寄存器
|
||||
byte[] request = new byte[8];
|
||||
request[0] = slaveId;
|
||||
request[1] = 0x03;
|
||||
request[2] = 0x00;
|
||||
request[3] = 0x00; // 起始地址 0x0000
|
||||
request[4] = 0x00;
|
||||
request[5] = 0x14; // 读取 20 个寄存器 (0x0000 ~ 0x0013)
|
||||
byte[] crc = CalculateCRC16(request, 6);
|
||||
request[6] = crc[0];
|
||||
request[7] = crc[1];
|
||||
|
||||
try
|
||||
{
|
||||
serialPort.Write(request, 0, request.Length);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Threading.Thread.Sleep(50);
|
||||
byte[] buffer = new byte[serialPort.BytesToRead];
|
||||
serialPort.Read(buffer, 0, buffer.Length);
|
||||
|
||||
if (buffer.Length < 9 || buffer[0] != slaveId || buffer[1] != 0x03)
|
||||
return;
|
||||
|
||||
// 解析温度 (0x0005)
|
||||
int tempIndex = 3 + (0x0005 - 0x0000) * 2;
|
||||
ushort rawTemp = (ushort)((buffer[tempIndex] << 8) | buffer[tempIndex + 1]);
|
||||
double temp = rawTemp / 100.0;
|
||||
|
||||
// 解析运行时间 (0x0007) - 这才是您要的恒温时间!
|
||||
int timeIndex = 3 + (0x0007 - 0x0000) * 2;
|
||||
ushort rawRunTime = (ushort)((buffer[timeIndex] << 8) | buffer[timeIndex + 1]);
|
||||
|
||||
// 根据 0x000F 的值判断单位(0=分钟,1=小时)
|
||||
int unitIndex = 3 + (0x000F - 0x0000) * 2;
|
||||
ushort timeUnit = (ushort)((buffer[unitIndex] << 8) | buffer[unitIndex + 1]);
|
||||
|
||||
int displayTime = rawRunTime;
|
||||
string unit = "分钟";
|
||||
if (timeUnit == 1)
|
||||
{
|
||||
displayTime = rawRunTime; // 小时
|
||||
unit = "小时";
|
||||
}
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
txtTestTemp.Text = temp.ToString("F2");
|
||||
|
||||
// 只有当运行时间 >0 时才显示,否则显示等待状态
|
||||
if (rawRunTime > 0)
|
||||
{
|
||||
txtThermostatTime.Text = displayTime.ToString();
|
||||
txtStatus.Text = $"温度: {temp:F2}℃ 已运行: {displayTime} {unit} 时间单位寄存器: {timeUnit}";
|
||||
}
|
||||
else
|
||||
{
|
||||
txtThermostatTime.Text = "0";
|
||||
txtStatus.Text = $"温度: {temp:F2}℃ 等待启动... (运行时间=0)";
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Dispatcher.Invoke(() => txtStatus.Text = $"接收错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
//private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// System.Threading.Thread.Sleep(50); // 等待数据收完
|
||||
// byte[] buffer = new byte[serialPort.BytesToRead];
|
||||
// serialPort.Read(buffer, 0, buffer.Length);
|
||||
|
||||
// // 最小有效响应长度:地址(1) + 功能码(1) + 字节数(1) + 数据(2*2) + CRC(2) = 9
|
||||
// if (buffer.Length < 9 || buffer[0] != slaveId || buffer[1] != 0x03)
|
||||
// return;
|
||||
|
||||
// // 提取数据:温度寄存器 (0x0005) 和 运行时间寄存器 (0x0007)
|
||||
// ushort rawTemp = (ushort)((buffer[3] << 8) | buffer[4]);
|
||||
// ushort rawRunTime = (ushort)((buffer[5] << 8) | buffer[6]);
|
||||
|
||||
// double temp = rawTemp / 100.0; // 协议规定小数点2位
|
||||
// int runTimeMinutes = rawRunTime; // 假设单位是分钟,直接显示
|
||||
|
||||
// // 更新 UI
|
||||
// Dispatcher.Invoke(() =>
|
||||
// {
|
||||
// // 更新试验温度(如果希望保留手动输入能力,可添加判断条件,这里直接覆盖)
|
||||
// txtTestTemp.Text = temp.ToString("F2");
|
||||
|
||||
// // 更新恒温时间
|
||||
// txtThermostatTime.Text = runTimeMinutes.ToString();
|
||||
|
||||
// txtStatus.Text = $"实时温度: {temp:F2}℃ 运行时间: {runTimeMinutes} min";
|
||||
// });
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Dispatcher.Invoke(() => txtStatus.Text = $"接收错误: {ex.Message}");
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
private byte[] CalculateCRC16(byte[] data, int length)
|
||||
{
|
||||
ushort crc = 0xFFFF;
|
||||
for (int pos = 0; pos < length; pos++)
|
||||
{
|
||||
crc ^= data[pos];
|
||||
for (int i = 8; i != 0; i--)
|
||||
{
|
||||
if ((crc & 0x0001) != 0)
|
||||
{
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new byte[] { (byte)(crc & 0xFF), (byte)(crc >> 8) };
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
readTimer?.Stop();
|
||||
readTimer?.Dispose();
|
||||
if (serialPort != null && serialPort.IsOpen)
|
||||
{
|
||||
serialPort.Close();
|
||||
serialPort.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 温度变化时自动更新恒温时间(表2)
|
||||
private void TxtTestTemp_TextChanged(object sender, TextChangedEventArgs e)
|
||||
@@ -310,5 +535,57 @@ namespace PetroleumViscosityTest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 第1次
|
||||
private void BtnStart1_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch1.Reset();
|
||||
stopwatch1.Start();
|
||||
}
|
||||
|
||||
private void BtnStop1_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch1.Stop();
|
||||
txtTime1.Text = (stopwatch1.Elapsed.TotalSeconds).ToString("F3");
|
||||
}
|
||||
|
||||
// 第2次
|
||||
private void BtnStart2_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch2.Reset();
|
||||
stopwatch2.Start();
|
||||
}
|
||||
|
||||
private void BtnStop2_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch2.Stop();
|
||||
txtTime2.Text = (stopwatch2.Elapsed.TotalSeconds).ToString("F3");
|
||||
}
|
||||
|
||||
// 第3次
|
||||
private void BtnStart3_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch3.Reset();
|
||||
stopwatch3.Start();
|
||||
}
|
||||
|
||||
private void BtnStop3_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch3.Stop();
|
||||
txtTime3.Text = (stopwatch3.Elapsed.TotalSeconds).ToString("F3");
|
||||
}
|
||||
|
||||
// 第4次
|
||||
private void BtnStart4_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch4.Reset();
|
||||
stopwatch4.Start();
|
||||
}
|
||||
|
||||
private void BtnStop4_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
stopwatch4.Stop();
|
||||
txtTime4.Text = (stopwatch4.Elapsed.TotalSeconds).ToString("F3");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,8 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Ports" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user