From fbab7e3c1710eec38ec4cbf4677642ec6ab5c83c Mon Sep 17 00:00:00 2001
From: xyy <544939200@qq.com>
Date: Mon, 8 Jun 2026 17:50:08 +0800
Subject: [PATCH]
---
Window1.xaml | 16 +----
Window1.xaml.cs | 164 ++++++++++++++++++++++++++++--------------------
2 files changed, 99 insertions(+), 81 deletions(-)
diff --git a/Window1.xaml b/Window1.xaml
index a66def7..b9eb523 100644
--- a/Window1.xaml
+++ b/Window1.xaml
@@ -37,8 +37,8 @@
-
-
+
+
@@ -47,17 +47,7 @@
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/Window1.xaml.cs b/Window1.xaml.cs
index 9992bc6..52768aa 100644
--- a/Window1.xaml.cs
+++ b/Window1.xaml.cs
@@ -13,6 +13,8 @@ namespace ConstantCurrentControl
{
private SerialPort _serialPort;
private bool _isConnected = false;
+ private DispatcherTimer _readTimer;
+ private List _receiveBuffer = new List(); // 接收缓存
public Window1()
{
@@ -24,6 +26,11 @@ namespace ConstantCurrentControl
{
cmbPort.ItemsSource = SerialPort.GetPortNames();
if (cmbPort.Items.Count > 0) cmbPort.SelectedIndex = 0;
+
+ // 初始化定时器(50ms 间隔,UI 线程)
+ _readTimer = new DispatcherTimer();
+ _readTimer.Interval = TimeSpan.FromMilliseconds(50);
+ _readTimer.Tick += ReadTimer_Tick;
}
#region 串口连接
@@ -39,7 +46,7 @@ namespace ConstantCurrentControl
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.ReadTimeout = 100;
_serialPort.WriteTimeout = 1000;
_serialPort.Open();
@@ -48,7 +55,14 @@ namespace ConstantCurrentControl
btnDisconnect.IsEnabled = true;
AddLog($"已连接 {port} @ {baud} bps");
- // 发送配置命令(不输出电流,只设置模式),同样异步等待但不死锁
+ // 清空接收缓存和串口缓冲区
+ _receiveBuffer.Clear();
+ _serialPort.DiscardInBuffer();
+
+ // 启动定时器读取
+ _readTimer.Start();
+
+ // 发送配置命令(不跟踪模式,byte8=0)
await ConfigureOptimalMode();
}
catch (Exception ex)
@@ -60,6 +74,7 @@ namespace ConstantCurrentControl
private void BtnDisconnect_Click(object sender, RoutedEventArgs e)
{
+ if (_readTimer != null) _readTimer.Stop();
if (_serialPort != null && _serialPort.IsOpen)
{
_serialPort.Close();
@@ -73,30 +88,62 @@ namespace ConstantCurrentControl
}
#endregion
- #region 最优模式配置(不发电流,只设 byte6=1, byte8=1)
- private async Task ConfigureOptimalMode()
+ #region 定时器读取数据
+ private void ReadTimer_Tick(object sender, EventArgs e)
{
- // 构造命令:电流 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] = rb50Hz.IsChecked == true ? (byte)1 : (byte)2;
- configCmd[8] = 0x00; // 开启跟踪模式
- configCmd[9] = 0x00;
- configCmd[10] = 0xFF;
- configCmd[11] = 0xFF;
+ if (!_isConnected || _serialPort == null || !_serialPort.IsOpen)
+ return;
- await SendCommandSafe(configCmd);
+ try
+ {
+ int bytesToRead = _serialPort.BytesToRead;
+ if (bytesToRead > 0)
+ {
+ byte[] buffer = new byte[bytesToRead];
+ _serialPort.Read(buffer, 0, bytesToRead);
+ _receiveBuffer.AddRange(buffer);
+
+ // 解析完整帧(12字节,以 FE FE 开头,FF FF 结尾)
+ ParseCompleteFrames();
+ }
+ }
+ catch (Exception ex)
+ {
+ AddLog($"读取错误: {ex.Message}");
+ }
+ }
+
+ private void ParseCompleteFrames()
+ {
+ for (int i = 0; i <= _receiveBuffer.Count - 12; i++)
+ {
+ if (_receiveBuffer[i] == 0xFE && _receiveBuffer[i + 1] == 0xFE &&
+ _receiveBuffer[i + 10] == 0xFF && _receiveBuffer[i + 11] == 0xFF)
+ {
+ byte[] frame = _receiveBuffer.Skip(i).Take(12).ToArray();
+ ProcessFrame(frame);
+ // 移除已处理的帧
+ _receiveBuffer.RemoveRange(0, i + 12);
+ i = -1; // 重新扫描
+ }
+ }
+ // 防止缓存无限增长
+ if (_receiveBuffer.Count > 200)
+ _receiveBuffer.RemoveRange(0, _receiveBuffer.Count - 200);
+ }
+
+ private void ProcessFrame(byte[] frame)
+ {
+ // 解析电流(byte4, byte5)
+ int rawCurrent = (frame[4] << 8) | frame[5];
+ double current = rawCurrent / 1000.0;
+
+ AddLog($"回采帧: {BitConverter.ToString(frame)} 电流={current:F3}A");
}
#endregion
- #region 安全的命令发送(异步读取,不卡UI)
- private async Task SendCommandSafe(byte[] command)
+ #region 发送命令(只写,不等待读)
+ private async Task SendCommand(byte[] command)
{
if (!_isConnected || _serialPort == null || !_serialPort.IsOpen)
{
@@ -106,53 +153,37 @@ namespace ConstantCurrentControl
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;
- }
+ return true;
}
catch (Exception ex)
{
- AddLog($"命令发送异常: {ex.Message}");
+ AddLog($"发送失败: {ex.Message}");
return false;
}
}
+
+ private async Task ConfigureOptimalMode()
+ {
+ byte[] configCmd = new byte[12];
+ configCmd[0] = 0xFE;
+ configCmd[1] = 0xFE;
+ configCmd[2] = 0x55;
+ configCmd[3] = 0xAA;
+ configCmd[4] = 0x00;
+ configCmd[5] = 0x00;
+ configCmd[6] = 0x01; // PC调节
+ configCmd[7] = rb50Hz.IsChecked == true ? (byte)1 : (byte)2;
+ configCmd[8] = 0x00; // 不跟踪(你实测稳定)
+ configCmd[9] = 0x00;
+ configCmd[10] = 0xFF;
+ configCmd[11] = 0xFF;
+ await SendCommand(configCmd);
+ }
#endregion
- #region 设定电流(平滑可选项,但为了简洁直接发)
+ #region UI操作
private async void BtnSet_Click(object sender, RoutedEventArgs e)
{
if (!_isConnected)
@@ -166,7 +197,6 @@ namespace ConstantCurrentControl
return;
}
- // 构造12字节电流命令
int raw = (int)(target * 1000);
byte cmdH = (byte)((raw >> 8) & 0xFF);
byte cmdL = (byte)(raw & 0xFF);
@@ -178,21 +208,20 @@ namespace ConstantCurrentControl
currentCmd[3] = 0xAA;
currentCmd[4] = cmdH;
currentCmd[5] = cmdL;
- currentCmd[6] = 0x01; // PC模式
+ currentCmd[6] = 0x01;
currentCmd[7] = rb50Hz.IsChecked == true ? (byte)1 : (byte)2;
- currentCmd[8] = 0x00; // 跟踪
+ currentCmd[8] = 0x00; // 不跟踪
currentCmd[9] = 0x00;
currentCmd[10] = 0xFF;
currentCmd[11] = 0xFF;
- await SendCommandSafe(currentCmd);
+ await SendCommand(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;
@@ -202,11 +231,11 @@ namespace ConstantCurrentControl
stopCmd[5] = 0x00;
stopCmd[6] = 0x01;
stopCmd[7] = rb50Hz.IsChecked == true ? (byte)1 : (byte)2;
- stopCmd[8] = 0x00;
+ stopCmd[8] = 0x00; // 不跟踪
stopCmd[9] = 0x00;
stopCmd[10] = 0xFF;
stopCmd[11] = 0xFF;
- await SendCommandSafe(stopCmd);
+ await SendCommand(stopCmd);
AddLog("禁止输出 (0A)");
}
@@ -218,7 +247,6 @@ namespace ConstantCurrentControl
if (lstLog.Items.Count > 50) lstLog.Items.RemoveAt(lstLog.Items.Count - 1);
});
}
+ #endregion
}
-}
-
-#endregion
\ No newline at end of file
+}
\ No newline at end of file