Files
ASTM-D7896-19TransientHot-W…/Services/FiveHalfDmmService.cs
2026-05-24 10:36:57 +08:00

173 lines
6.2 KiB
C#
Raw Permalink 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.IO.Ports;
using System.Threading.Tasks;
using System.Linq;
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 = 5000; // 增加超时,批量数据可能需要更长时间
_serialPort.WriteTimeout = 1000;
_serialPort.NewLine = "\n"; // 结束符为 LF
}
public void Open()
{
if (!_serialPort.IsOpen)
_serialPort.Open();
}
public void Close()
{
if (_serialPort.IsOpen)
_serialPort.Close();
}
public bool IsOpen => _serialPort?.IsOpen == true;
// ========== 核心通信方法 ==========
private async Task<string> QueryAsync(string command)
{
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
return await Task.Run(() =>
{
lock (_serialPort)
{
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.WriteLine(command);
System.Diagnostics.Debug.WriteLine($"[发送] {command}");
// 读取直到遇到换行符(批量数据可能很长,但 ReadLine 会一直读到 \n
string response = _serialPort.ReadLine();
System.Diagnostics.Debug.WriteLine($"[接收] {response}");
return response.Trim();
}
});
}
private async Task SendCommandAsync(string command)
{
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
await Task.Run(() =>
{
lock (_serialPort)
{
_serialPort.WriteLine(command);
}
});
}
// ========== 配置高速直流电压测量基于8255文档 ==========
public async Task ConfigureHighSpeedDcvAsync()
{
// 1. 复位到已知状态(可选)
await SendCommandAsync("*RST");
await Task.Delay(100);
// 2. 固定量程(推荐手动设定,例如 1V根据实际信号调整
// 文档中量程可选 200mV, 2V, 20V, 200V, 1000V
await SendCommandAsync("VOLT:DC:RANG 1");
// 3. 设置分辨率为 FAST高速模式
await SendCommandAsync("VOLT:DC:RES FAST");
// 4. 触发源设为 BUS软件触发
await SendCommandAsync("TRIG:SOUR BUS");
// 5. 关闭自动延迟,延迟设为 0
await SendCommandAsync("TRIG:DEL:AUTO OFF");
await SendCommandAsync("TRIG:DEL 0");
}
// ========== 方案一READ? 一次性批量采集(推荐,稳定可靠) ==========
/// <summary>
/// 批量读取指定数量的电压值(使用 READ? 命令)
/// </summary>
/// <param name="sampleCount">采样点数,如 400</param>
/// <returns>电压值数组(单位:伏特)</returns>
public async Task<double[]> ReadBatchAsync(int sampleCount)
{
// 设置采样点数
await SendCommandAsync($"SAMP:COUN {sampleCount}");
// 发送 READ?,仪器将自动完成触发、采集并返回所有结果
string response = await QueryAsync("READ?");
// 解析逗号分隔的数值
return ParseResponse(response, sampleCount);
}
// ========== 方案二INIT + *TRG + FETCh? 流程(保留,以备特殊场景) ==========
public async Task PrepareBatchAsync(int sampleCount)
{
await SendCommandAsync($"SAMP:COUN {sampleCount}");
await SendCommandAsync("INIT");
}
public async Task TriggerAsync()
{
await SendCommandAsync("*TRG");
}
public async Task<double[]> FetchBatchAsync()
{
string response = await QueryAsync("FETCh?");
return ParseResponse(response, null); // 不检查数量,直接解析
}
// ========== 辅助方法 ==========
private double[] ParseResponse(string response, int? expectedCount = null)
{
if (string.IsNullOrWhiteSpace(response))
throw new Exception("返回数据为空");
string[] parts = response.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
double[] values = new double[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
if (!double.TryParse(parts[i].Trim(),
System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture,
out values[i]))
{
throw new Exception($"解析失败: {parts[i]},原始响应: {response}");
}
}
if (expectedCount.HasValue && values.Length != expectedCount.Value)
System.Diagnostics.Debug.WriteLine($"警告:实际点数 {values.Length},期望 {expectedCount.Value}");
return values;
}
// ========== 单次读取(保留兼容) ==========
public async Task<double> ReadVoltageAsync()
{
string resp = await QueryAsync("MEAS:VOLT: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;
}
}
}
}