This commit is contained in:
xyy
2026-05-24 10:36:57 +08:00
parent 24f438b81a
commit eb95de74ed
4 changed files with 140 additions and 97 deletions

View File

@@ -13,9 +13,9 @@ namespace ASTM_D7896_Tester.Services
public FiveHalfDmmService(string portName, int baudRate = 115200)
{
_serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
_serialPort.ReadTimeout = 2000;
_serialPort.ReadTimeout = 5000; // 增加超时,批量数据可能需要更长时间
_serialPort.WriteTimeout = 1000;
_serialPort.NewLine = "\n";
_serialPort.NewLine = "\n"; // 结束符为 LF
}
public void Open()
@@ -32,9 +32,7 @@ namespace ASTM_D7896_Tester.Services
public bool IsOpen => _serialPort?.IsOpen == true;
/// <summary>
/// 发送命令并等待响应同步读写但因在Task.Run中执行不阻塞UI
/// </summary>
// ========== 核心通信方法 ==========
private async Task<string> QueryAsync(string command)
{
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
@@ -42,13 +40,12 @@ namespace ASTM_D7896_Tester.Services
{
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();
@@ -56,16 +53,6 @@ namespace ASTM_D7896_Tester.Services
});
}
public string TestCommunication()
{
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
_serialPort.DiscardInBuffer();
_serialPort.WriteLine("*IDN?");
return _serialPort.ReadLine().Trim();
}
private async Task SendCommandAsync(string command)
{
if (!_serialPort.IsOpen) throw new InvalidOperationException("串口未打开");
@@ -78,71 +65,97 @@ namespace ASTM_D7896_Tester.Services
});
}
/// <summary>
/// 配置为高速直流电压测量根据8255文档
/// </summary>
// ========== 配置高速直流电压测量基于8255文档 ==========
public async Task ConfigureHighSpeedDcvAsync()
{
// 配置直流电压,自动量程
await SendCommandAsync("CONFigure:VOLTage:DC AUTO");
// 设置精度为FAST高速模式
await SendCommandAsync("SENSe:VOLTage:DC:RESolution FAST");
// 使用软件触发
await SendCommandAsync("TRIGger:SOURce BUS");
// 关闭自动延迟
await SendCommandAsync("TRIGger:DELay:AUTO OFF");
await SendCommandAsync("TRIGger:DELay 0");
// 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($"SAMPle:COUNt {sampleCount}");
await SendCommandAsync("INITiate");
await SendCommandAsync($"SAMP:COUN {sampleCount}");
await SendCommandAsync("INIT");
}
/// <summary>
/// 发送软件触发信号
/// </summary>
public async Task TriggerAsync()
{
await SendCommandAsync("*TRG");
}
/// <summary>
/// 获取批量采集结果
/// </summary>
public async Task<double[]> FetchBatchAsync()
{
string response = await QueryAsync("FETCh?");
if (string.IsNullOrWhiteSpace(response))
throw new Exception("FETCh? 返回空响应");
return ParseResponse(response, null); // 不检查数量,直接解析
}
// ========== 辅助方法 ==========
private double[] ParseResponse(string response, int? expectedCount = null)
{
if (string.IsNullOrWhiteSpace(response))
throw new Exception("返回数据为空");
// 文档示例返回值如 "+1.234500E-02,+2.345600E-02"
string[] parts = response.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
double[] values = new double[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
string valStr = parts[i].Trim();
if (!double.TryParse(valStr, System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture, out values[i]))
if (!double.TryParse(parts[i].Trim(),
System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture,
out values[i]))
{
throw new Exception($"解析失败: {valStr},原始响应: {response}");
throw new Exception($"解析失败: {parts[i]},原始响应: {response}");
}
}
if (expectedCount.HasValue && values.Length != expectedCount.Value)
System.Diagnostics.Debug.WriteLine($"警告:实际点数 {values.Length},期望 {expectedCount.Value}");
return values;
}
/// <summary>
/// 单次读取电压
/// </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))
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}");
}