Compare commits
2 Commits
76c911084e
...
8681cc0163
| Author | SHA1 | Date | |
|---|---|---|---|
| 8681cc0163 | |||
| ae5803431b |
2
App.xaml
2
App.xaml
@@ -1,7 +1,7 @@
|
|||||||
<Application x:Class="ASTM_D7896_Tester.App"
|
<Application x:Class="ASTM_D7896_Tester.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:converters="clr-namespace:ASTM_D7896_Tester.Converters"
|
xmlns:converters="clr-namespace:ASTM_D7896_Tester.Converters" StartupUri="Window1.xaml"
|
||||||
>
|
>
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||||
|
|||||||
@@ -12,14 +12,11 @@ using PdfSharpCore.Pdf;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Ports;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Threading;
|
|
||||||
|
|
||||||
namespace ASTM_D7896_Tester.ViewModels;
|
namespace ASTM_D7896_Tester.ViewModels;
|
||||||
|
|
||||||
@@ -124,9 +121,6 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
_th1953Ustd = new Th1963LanService();
|
_th1953Ustd = new Th1963LanService();
|
||||||
|
|
||||||
StartBackgroundMonitoring();
|
StartBackgroundMonitoring();
|
||||||
|
|
||||||
Task.Run(() => initPort());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void StartBackgroundMonitoring()
|
private async void StartBackgroundMonitoring()
|
||||||
@@ -206,7 +200,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
BtnSet();
|
|
||||||
|
|
||||||
|
|
||||||
await _th1963Ustd.ConnectAsync("192.168.1.12", 45454); // 改为实际IP
|
await _th1963Ustd.ConnectAsync("192.168.1.12", 45454); // 改为实际IP
|
||||||
@@ -450,7 +444,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
// 测量间隔(即使舍弃也等待,让样品恢复)
|
// 测量间隔(即使舍弃也等待,让样品恢复)
|
||||||
if (validCount < requiredCount && !_stopRequested && attemptCount < maxAttempts)
|
if (validCount < requiredCount && !_stopRequested && attemptCount < maxAttempts)
|
||||||
{
|
{
|
||||||
try { await Task.Delay(_config.TestParameters.IntervalSeconds * 1000, _testCts.Token); } catch (OperationCanceledException) { break; }
|
try { await Task.Delay(_config.TestParameters.IntervalSeconds * 100, _testCts.Token); } catch (OperationCanceledException) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,18 +776,6 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
AverageVolumetricHeatCapacity = Measurements.Average(m => m.VolumetricHeatCapacity);
|
AverageVolumetricHeatCapacity = Measurements.Average(m => m.VolumetricHeatCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[RelayCommand]
|
|
||||||
//private void Reset()
|
|
||||||
//{
|
|
||||||
// //Measurements.Clear();
|
|
||||||
// //AverageThermalConductivity = AverageThermalDiffusivity = AverageVolumetricHeatCapacity = 0;
|
|
||||||
// //CurrentMeasurementIndex = 0;
|
|
||||||
// //StatusMessage = "已重置";
|
|
||||||
// //TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
// //TemperatureCurveModel = null;
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void Reset()
|
private void Reset()
|
||||||
{
|
{
|
||||||
@@ -802,18 +784,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
CurrentMeasurementIndex = 0;
|
CurrentMeasurementIndex = 0;
|
||||||
StatusMessage = "已重置";
|
StatusMessage = "已重置";
|
||||||
TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
TemperatureCurveModel = null;
|
||||||
// 清空曲线:新建一个空白的 PlotModel 替换原来的
|
|
||||||
TemperatureCurveModel = new PlotModel
|
|
||||||
{
|
|
||||||
Title = "温升与冷却曲线",
|
|
||||||
Background = OxyColors.White
|
|
||||||
};
|
|
||||||
TemperatureCurveModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "时间 (s)" });
|
|
||||||
TemperatureCurveModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "温升 (℃)" });
|
|
||||||
TemperatureCurveModel.InvalidatePlot(true);
|
|
||||||
|
|
||||||
CurveTitle = "温升曲线";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -1071,146 +1042,4 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private SerialPort _serialPort;
|
|
||||||
private bool _isConnected = false;
|
|
||||||
|
|
||||||
private async Task initPort()
|
|
||||||
{
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string port = "COM10";
|
|
||||||
int baud = 19200;
|
|
||||||
_serialPort = new SerialPort(port, baud, Parity.None, 8, StopBits.One);
|
|
||||||
_serialPort.ReadTimeout = 1000; // 关键:避免永久阻塞
|
|
||||||
_serialPort.WriteTimeout = 1000;
|
|
||||||
_serialPort.Open();
|
|
||||||
|
|
||||||
_isConnected = true;
|
|
||||||
|
|
||||||
|
|
||||||
// 发送配置命令(不输出电流,只设置模式),同样异步等待但不死锁
|
|
||||||
await ConfigureOptimalMode();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"连接失败: {ex.Message}");
|
|
||||||
_isConnected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ConfigureOptimalMode()
|
|
||||||
{
|
|
||||||
// 构造命令:电流 0,但强制 PC 模式和跟踪模式
|
|
||||||
byte[] configCmd = new byte[12];
|
|
||||||
configCmd[0] = 0xFE;
|
|
||||||
configCmd[1] = 0xFE;
|
|
||||||
configCmd[2] = 0x55; // 识别码高
|
|
||||||
configCmd[3] = 0xAA; // 识别码低
|
|
||||||
configCmd[4] = 0x00; // 电流高字节 (0A)
|
|
||||||
configCmd[5] = 0x00; // 电流低字节
|
|
||||||
configCmd[6] = 0x01; // PC调节模式
|
|
||||||
configCmd[7] = 0x01;
|
|
||||||
configCmd[8] = 0x00; // 开启跟踪模式
|
|
||||||
configCmd[9] = 0x00;
|
|
||||||
configCmd[10] = 0xFF;
|
|
||||||
configCmd[11] = 0xFF;
|
|
||||||
|
|
||||||
await SendCommandSafe(configCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 安全的命令发送(异步读取,不卡UI)
|
|
||||||
private async Task<bool> SendCommandSafe(byte[] command)
|
|
||||||
{
|
|
||||||
if (!_isConnected || _serialPort == null || !_serialPort.IsOpen)
|
|
||||||
{
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 清空缓冲区
|
|
||||||
_serialPort.DiscardInBuffer();
|
|
||||||
_serialPort.DiscardOutBuffer();
|
|
||||||
|
|
||||||
// 发送命令
|
|
||||||
await _serialPort.BaseStream.WriteAsync(command, 0, command.Length);
|
|
||||||
|
|
||||||
|
|
||||||
// 异步读取12字节(带超时)
|
|
||||||
byte[] buffer = new byte[12];
|
|
||||||
int totalRead = 0;
|
|
||||||
DateTime start = DateTime.Now;
|
|
||||||
while (totalRead < 12 && (DateTime.Now - start).TotalMilliseconds < 1500)
|
|
||||||
{
|
|
||||||
if (_serialPort.BytesToRead > 0)
|
|
||||||
{
|
|
||||||
int read = await _serialPort.BaseStream.ReadAsync(buffer, totalRead, 12 - totalRead);
|
|
||||||
if (read > 0) totalRead += read;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
await Task.Delay(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalRead == 12)
|
|
||||||
{
|
|
||||||
|
|
||||||
// 解析回采电流 (byte4, byte5)
|
|
||||||
int rawCurrent = (buffer[4] << 8) | buffer[5];
|
|
||||||
double actualCurrent = rawCurrent / 1000.0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private async void BtnSet()
|
|
||||||
{
|
|
||||||
if (!_isConnected)
|
|
||||||
{
|
|
||||||
MessageBox.Show("请先连接串口");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double target = 0.650;
|
|
||||||
|
|
||||||
// 构造12字节电流命令
|
|
||||||
int raw = (int)(target * 1000);
|
|
||||||
byte cmdH = (byte)((raw >> 8) & 0xFF);
|
|
||||||
byte cmdL = (byte)(raw & 0xFF);
|
|
||||||
|
|
||||||
byte[] currentCmd = new byte[12];
|
|
||||||
currentCmd[0] = 0xFE;
|
|
||||||
currentCmd[1] = 0xFE;
|
|
||||||
currentCmd[2] = 0x55;
|
|
||||||
currentCmd[3] = 0xAA;
|
|
||||||
currentCmd[4] = cmdH;
|
|
||||||
currentCmd[5] = cmdL;
|
|
||||||
currentCmd[6] = 0x01;
|
|
||||||
currentCmd[7] = 1;
|
|
||||||
currentCmd[8] = 0;
|
|
||||||
currentCmd[9] = 0x00;
|
|
||||||
currentCmd[10] = 0xFF;
|
|
||||||
currentCmd[11] = 0xFF;
|
|
||||||
|
|
||||||
await SendCommandSafe(currentCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
74
Window1.xaml
Normal file
74
Window1.xaml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<Window x:Class="ConstantCurrentControl.Window1"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="SN-5A 恒流源控制" Height="500" Width="650"
|
||||||
|
WindowStartupLocation="CenterScreen">
|
||||||
|
<Grid Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- 串口设置 -->
|
||||||
|
<GroupBox Header="串口设置" Grid.Row="0" Margin="5">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="5">
|
||||||
|
<Label Content="端口:"/>
|
||||||
|
<ComboBox x:Name="cmbPort" Width="80" IsEditable="True"/>
|
||||||
|
<Label Content="波特率:" Margin="10,0,0,0"/>
|
||||||
|
<ComboBox x:Name="cmbBaudrate" Width="80" SelectedIndex="1">
|
||||||
|
<ComboBoxItem>9600</ComboBoxItem>
|
||||||
|
<ComboBoxItem>19200</ComboBoxItem>
|
||||||
|
<ComboBoxItem>38400</ComboBoxItem>
|
||||||
|
<ComboBoxItem>115200</ComboBoxItem>
|
||||||
|
</ComboBox>
|
||||||
|
<Button x:Name="btnConnect" Content="连接" Click="BtnConnect_Click" Width="60" Margin="10,0,0,0"/>
|
||||||
|
<Button x:Name="btnDisconnect" Content="断开" Click="BtnDisconnect_Click" Width="60" Margin="5,0,0,0" IsEnabled="False"/>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- 参数设置 -->
|
||||||
|
<GroupBox Header="输出参数(最优稳定性)" Grid.Row="1" Margin="5">
|
||||||
|
<StackPanel Margin="5">
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
|
||||||
|
<Label Content="频率:"/>
|
||||||
|
<RadioButton x:Name="rb50Hz" Content="50 Hz" GroupName="Freq" IsChecked="True" Margin="5,0,15,0"/>
|
||||||
|
<RadioButton x:Name="rb60Hz" Content="60 Hz" GroupName="Freq"/>
|
||||||
|
<Label Content=" 设定电流 (A):" Margin="20,0,0,0"/>
|
||||||
|
<TextBox x:Name="txtSetCurrent" Text="0.65" Width="80" TextAlignment="Right"/>
|
||||||
|
<Label Content="A"/>
|
||||||
|
<Button x:Name="btnSet" Content="直接设定" Click="BtnSet_Click" Width="80" Margin="10,0,0,0"/>
|
||||||
|
<Button x:Name="btnStop" Content="禁止输出" Click="BtnStop_Click" Width="80" Margin="5,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox x:Name="chkSmooth" Content="启用平滑过渡 (步进0.05A, 间隔200ms)" IsChecked="True" Margin="0,5,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- 反馈显示 -->
|
||||||
|
<GroupBox Header="实际回采 (软件滑动平均滤波)" Grid.Row="2" Margin="5">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="当前实际电流:" Grid.Column="0" FontWeight="Bold"/>
|
||||||
|
<TextBox x:Name="txtActualCurrent" Grid.Column="1" Text="0.000" IsReadOnly="True" FontSize="20" FontWeight="Bold" TextAlignment="Center" Background="LightYellow"/>
|
||||||
|
</Grid>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- 日志 -->
|
||||||
|
<GroupBox Header="通讯日志" Grid.Row="3" Margin="5">
|
||||||
|
<ListBox x:Name="lstLog" Height="120" FontFamily="Consolas"/>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- 说明 -->
|
||||||
|
<TextBlock Grid.Row="4" TextWrapping="Wrap" FontSize="11" Foreground="Gray" Margin="5">
|
||||||
|
※ 协议:12字节命令 (FE FE + 识别码 + 电流高/低 + 模式+频率+跟踪 + FF FF)
|
||||||
|
※ 开启跟踪 (byte8=1) 和 PC调节 (byte6=1) 可获最低噪声与最小温漂
|
||||||
|
※ 平滑过渡可避免电流突变产生的冲击噪声
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
223
Window1.xaml.cs
Normal file
223
Window1.xaml.cs
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace ConstantCurrentControl
|
||||||
|
{
|
||||||
|
public partial class Window1 : Window
|
||||||
|
{
|
||||||
|
private SerialPort _serialPort;
|
||||||
|
private bool _isConnected = false;
|
||||||
|
|
||||||
|
public Window1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Loaded += MainWindow_Loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
cmbPort.ItemsSource = SerialPort.GetPortNames();
|
||||||
|
if (cmbPort.Items.Count > 0) cmbPort.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 串口连接
|
||||||
|
private async void BtnConnect_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (cmbPort.SelectedItem == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("请选择串口号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string port = cmbPort.SelectedItem.ToString();
|
||||||
|
int baud = int.Parse((cmbBaudrate.SelectedItem as ComboBoxItem).Content.ToString());
|
||||||
|
_serialPort = new SerialPort(port, baud, Parity.None, 8, StopBits.One);
|
||||||
|
_serialPort.ReadTimeout = 1000; // 关键:避免永久阻塞
|
||||||
|
_serialPort.WriteTimeout = 1000;
|
||||||
|
_serialPort.Open();
|
||||||
|
|
||||||
|
_isConnected = true;
|
||||||
|
btnConnect.IsEnabled = false;
|
||||||
|
btnDisconnect.IsEnabled = true;
|
||||||
|
AddLog($"已连接 {port} @ {baud} bps");
|
||||||
|
|
||||||
|
// 发送配置命令(不输出电流,只设置模式),同样异步等待但不死锁
|
||||||
|
await ConfigureOptimalMode();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"连接失败: {ex.Message}");
|
||||||
|
_isConnected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnDisconnect_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_serialPort != null && _serialPort.IsOpen)
|
||||||
|
{
|
||||||
|
_serialPort.Close();
|
||||||
|
_serialPort.Dispose();
|
||||||
|
_serialPort = null;
|
||||||
|
}
|
||||||
|
_isConnected = false;
|
||||||
|
btnConnect.IsEnabled = true;
|
||||||
|
btnDisconnect.IsEnabled = false;
|
||||||
|
AddLog("已断开连接");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 最优模式配置(不发电流,只设 byte6=1, byte8=1)
|
||||||
|
private async Task ConfigureOptimalMode()
|
||||||
|
{
|
||||||
|
// 构造命令:电流 0,但强制 PC 模式和跟踪模式
|
||||||
|
byte[] configCmd = new byte[12];
|
||||||
|
configCmd[0] = 0xFE;
|
||||||
|
configCmd[1] = 0xFE;
|
||||||
|
configCmd[2] = 0x55; // 识别码高
|
||||||
|
configCmd[3] = 0xAA; // 识别码低
|
||||||
|
configCmd[4] = 0x00; // 电流高字节 (0A)
|
||||||
|
configCmd[5] = 0x00; // 电流低字节
|
||||||
|
configCmd[6] = 0x01; // PC调节模式
|
||||||
|
configCmd[7] = 1;
|
||||||
|
configCmd[8] = 0; // 开启跟踪模式
|
||||||
|
configCmd[9] = 0x00;
|
||||||
|
configCmd[10] = 0xFF;
|
||||||
|
configCmd[11] = 0xFF;
|
||||||
|
|
||||||
|
await SendCommandSafe(configCmd);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 安全的命令发送(异步读取,不卡UI)
|
||||||
|
private async Task<bool> SendCommandSafe(byte[] command)
|
||||||
|
{
|
||||||
|
if (!_isConnected || _serialPort == null || !_serialPort.IsOpen)
|
||||||
|
{
|
||||||
|
AddLog("串口未打开");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 清空缓冲区
|
||||||
|
_serialPort.DiscardInBuffer();
|
||||||
|
_serialPort.DiscardOutBuffer();
|
||||||
|
|
||||||
|
// 发送命令
|
||||||
|
await _serialPort.BaseStream.WriteAsync(command, 0, command.Length);
|
||||||
|
AddLog($"发送: {BitConverter.ToString(command)}");
|
||||||
|
|
||||||
|
// 异步读取12字节(带超时)
|
||||||
|
byte[] buffer = new byte[12];
|
||||||
|
int totalRead = 0;
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
while (totalRead < 12 && (DateTime.Now - start).TotalMilliseconds < 1500)
|
||||||
|
{
|
||||||
|
if (_serialPort.BytesToRead > 0)
|
||||||
|
{
|
||||||
|
int read = await _serialPort.BaseStream.ReadAsync(buffer, totalRead, 12 - totalRead);
|
||||||
|
if (read > 0) totalRead += read;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
await Task.Delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalRead == 12)
|
||||||
|
{
|
||||||
|
AddLog($"接收: {BitConverter.ToString(buffer)}");
|
||||||
|
// 解析回采电流 (byte4, byte5)
|
||||||
|
int rawCurrent = (buffer[4] << 8) | buffer[5];
|
||||||
|
double actualCurrent = rawCurrent / 1000.0;
|
||||||
|
Dispatcher.Invoke(() => txtActualCurrent.Text = actualCurrent.ToString("F3"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLog($"接收超时或字节数不足: {totalRead}/12");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
AddLog($"命令发送异常: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 设定电流(平滑可选项,但为了简洁直接发)
|
||||||
|
private async void BtnSet_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_isConnected)
|
||||||
|
{
|
||||||
|
MessageBox.Show("请先连接串口");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!double.TryParse(txtSetCurrent.Text, out double target) || target < 0 || target > 5)
|
||||||
|
{
|
||||||
|
MessageBox.Show("电流需为 0~5.000 A");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造12字节电流命令
|
||||||
|
int raw = (int)(target * 1000);
|
||||||
|
byte cmdH = (byte)((raw >> 8) & 0xFF);
|
||||||
|
byte cmdL = (byte)(raw & 0xFF);
|
||||||
|
|
||||||
|
byte[] currentCmd = new byte[12];
|
||||||
|
currentCmd[0] = 0xFE;
|
||||||
|
currentCmd[1] = 0xFE;
|
||||||
|
currentCmd[2] = 0x55;
|
||||||
|
currentCmd[3] = 0xAA;
|
||||||
|
currentCmd[4] = cmdH;
|
||||||
|
currentCmd[5] = cmdL;
|
||||||
|
currentCmd[6] = 0x01; // PC模式
|
||||||
|
currentCmd[7] = 1;
|
||||||
|
currentCmd[8] = 0; // 跟踪
|
||||||
|
currentCmd[9] = 0x00;
|
||||||
|
currentCmd[10] = 0xFF;
|
||||||
|
currentCmd[11] = 0xFF;
|
||||||
|
|
||||||
|
await SendCommandSafe(currentCmd);
|
||||||
|
AddLog($"设定电流 = {target:F3} A");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void BtnStop_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_isConnected) return;
|
||||||
|
// 发送电流0
|
||||||
|
byte[] stopCmd = new byte[12];
|
||||||
|
stopCmd[0] = 0xFE;
|
||||||
|
stopCmd[1] = 0xFE;
|
||||||
|
stopCmd[2] = 0x55;
|
||||||
|
stopCmd[3] = 0xAA;
|
||||||
|
stopCmd[4] = 0x00;
|
||||||
|
stopCmd[5] = 0x00;
|
||||||
|
stopCmd[6] = 0x01;
|
||||||
|
stopCmd[7] = 1; // 50Hz
|
||||||
|
stopCmd[8] = 0;
|
||||||
|
stopCmd[9] = 0x00;
|
||||||
|
stopCmd[10] = 0xFF;
|
||||||
|
stopCmd[11] = 0xFF;
|
||||||
|
await SendCommandSafe(stopCmd);
|
||||||
|
AddLog("禁止输出 (0A)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddLog(string msg)
|
||||||
|
{
|
||||||
|
Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
lstLog.Items.Insert(0, $"{DateTime.Now:HH:mm:ss} {msg}");
|
||||||
|
if (lstLog.Items.Count > 50) lstLog.Items.RemoveAt(lstLog.Items.Count - 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
Reference in New Issue
Block a user