Files
ASTM-D7896-19TransientHot-W…/Window1.xaml.cs
2026-06-08 17:33:46 +08:00

223 lines
7.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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