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 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? 一次性批量采集(推荐,稳定可靠) ========== /// /// 批量读取指定数量的电压值(使用 READ? 命令) /// /// 采样点数,如 400 /// 电压值数组(单位:伏特) public async Task 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 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 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; } } } }