2026-05-20 19:46:52 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO.Ports;
|
|
|
|
|
|
using System.Threading.Tasks;
|
2026-05-23 21:18:46 +08:00
|
|
|
|
using System.Linq;
|
2026-05-20 19:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ASTM_D7896_Tester.Services
|
|
|
|
|
|
{
|
|
|
|
|
|
public class FiveHalfDmmService : IDisposable
|
|
|
|
|
|
{
|
|
|
|
|
|
private SerialPort _serialPort;
|
|
|
|
|
|
private bool _disposed;
|
|
|
|
|
|
|
|
|
|
|
|
public FiveHalfDmmService(string portName, int baudRate = 115200)
|
|
|
|
|
|
{
|
|
|
|
|
|
_serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
|
|
|
|
|
|
_serialPort.ReadTimeout = 2000;
|
|
|
|
|
|
_serialPort.WriteTimeout = 1000;
|
|
|
|
|
|
_serialPort.NewLine = "\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Open()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_serialPort.IsOpen)
|
|
|
|
|
|
_serialPort.Open();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Close()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_serialPort.IsOpen)
|
|
|
|
|
|
_serialPort.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool IsOpen => _serialPort?.IsOpen == true;
|
|
|
|
|
|
|
2026-05-23 21:18:46 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 发送命令并等待响应(同步读写,但因在Task.Run中执行,不阻塞UI)
|
|
|
|
|
|
/// </summary>
|
2026-05-20 19:46:52 +08:00
|
|
|
|
private async Task<string> QueryAsync(string command)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
|
2026-05-23 21:18:46 +08:00
|
|
|
|
return await Task.Run(() =>
|
2026-05-20 19:46:52 +08:00
|
|
|
|
{
|
2026-05-23 21:18:46 +08:00
|
|
|
|
lock (_serialPort)
|
2026-05-20 19:46:52 +08:00
|
|
|
|
{
|
2026-05-23 21:18:46 +08:00
|
|
|
|
// 清空缓冲区
|
|
|
|
|
|
_serialPort.DiscardInBuffer();
|
|
|
|
|
|
_serialPort.DiscardOutBuffer();
|
|
|
|
|
|
|
2026-05-20 19:46:52 +08:00
|
|
|
|
_serialPort.WriteLine(command);
|
2026-05-23 21:18:46 +08:00
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[发送] {command}");
|
|
|
|
|
|
|
|
|
|
|
|
string response = _serialPort.ReadLine();
|
|
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[接收] {response}");
|
|
|
|
|
|
return response.Trim();
|
2026-05-20 19:46:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-23 21:18:46 +08:00
|
|
|
|
|
|
|
|
|
|
public string TestCommunication()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
|
|
|
|
|
|
_serialPort.DiscardInBuffer();
|
|
|
|
|
|
_serialPort.WriteLine("*IDN?");
|
|
|
|
|
|
return _serialPort.ReadLine().Trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-20 19:46:52 +08:00
|
|
|
|
private async Task SendCommandAsync(string command)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
|
2026-05-23 21:18:46 +08:00
|
|
|
|
await Task.Run(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_serialPort)
|
|
|
|
|
|
{
|
|
|
|
|
|
_serialPort.WriteLine(command);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-05-20 19:46:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-05-23 21:18:46 +08:00
|
|
|
|
/// 配置为高速直流电压测量(根据8255文档)
|
2026-05-20 19:46:52 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task ConfigureHighSpeedDcvAsync()
|
|
|
|
|
|
{
|
2026-05-23 21:18:46 +08:00
|
|
|
|
// 配置直流电压,自动量程
|
2026-05-20 19:46:52 +08:00
|
|
|
|
await SendCommandAsync("CONFigure:VOLTage:DC AUTO");
|
2026-05-23 21:18:46 +08:00
|
|
|
|
// 设置精度为FAST(高速模式)
|
2026-05-20 19:46:52 +08:00
|
|
|
|
await SendCommandAsync("SENSe:VOLTage:DC:RESolution FAST");
|
2026-05-23 21:18:46 +08:00
|
|
|
|
// 使用软件触发
|
|
|
|
|
|
await SendCommandAsync("TRIGger:SOURce BUS");
|
|
|
|
|
|
// 关闭自动延迟
|
2026-05-20 19:46:52 +08:00
|
|
|
|
await SendCommandAsync("TRIGger:DELay:AUTO OFF");
|
|
|
|
|
|
await SendCommandAsync("TRIGger:DELay 0");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 预置采样点数并进入等待触发状态
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task PrepareBatchAsync(int sampleCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
await SendCommandAsync($"SAMPle:COUNt {sampleCount}");
|
|
|
|
|
|
await SendCommandAsync("INITiate");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-05-23 21:18:46 +08:00
|
|
|
|
/// 发送软件触发信号
|
2026-05-20 19:46:52 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task TriggerAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
await SendCommandAsync("*TRG");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-05-23 21:18:46 +08:00
|
|
|
|
/// 获取批量采集结果
|
2026-05-20 19:46:52 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<double[]> FetchBatchAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
string response = await QueryAsync("FETCh?");
|
2026-05-23 21:18:46 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(response))
|
|
|
|
|
|
throw new Exception("FETCh? 返回空响应");
|
|
|
|
|
|
|
|
|
|
|
|
// 文档示例返回值如 "+1.234500E-02,+2.345600E-02"
|
2026-05-20 19:46:52 +08:00
|
|
|
|
string[] parts = response.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
double[] values = new double[parts.Length];
|
|
|
|
|
|
for (int i = 0; i < parts.Length; i++)
|
|
|
|
|
|
{
|
2026-05-23 21:18:46 +08:00
|
|
|
|
string valStr = parts[i].Trim();
|
|
|
|
|
|
if (!double.TryParse(valStr, System.Globalization.NumberStyles.Float,
|
2026-05-20 19:46:52 +08:00
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out values[i]))
|
2026-05-23 21:18:46 +08:00
|
|
|
|
{
|
|
|
|
|
|
throw new Exception($"解析失败: {valStr},原始响应: {response}");
|
|
|
|
|
|
}
|
2026-05-20 19:46:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
return values;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-05-23 21:18:46 +08:00
|
|
|
|
/// 单次读取电压
|
2026-05-20 19:46:52 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public async Task<double> ReadVoltageAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
string resp = await QueryAsync("MEASure:VOLTage:DC?");
|
|
|
|
|
|
if (double.TryParse(resp, System.Globalization.NumberStyles.Float,
|
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out double value))
|
|
|
|
|
|
return value;
|
|
|
|
|
|
throw new Exception($"无效响应: {resp}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_disposed)
|
|
|
|
|
|
{
|
|
|
|
|
|
Close();
|
|
|
|
|
|
_serialPort?.Dispose();
|
|
|
|
|
|
_disposed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|