0
点赞
收藏
分享

微信扫一扫

测试开发知识体系(阶段一)3.​​C#硬件集成开发


3.1 串口通信深度实战

3.1.1 工业级串口通信框架

using System.IO.Ports;
using System.Threading;

public class IndustrialSerialPort {
    private SerialPort _port;
    private Thread _readThread;
    private bool _running;

    public void Connect(string portName, int baudRate) {
        _port = new SerialPort(portName, baudRate) {
            Parity = Parity.None,
            DataBits = 8,
            StopBits = StopBits.One,
            Handshake = Handshake.RequestToSend,
            ReadTimeout = 1500,
            WriteTimeout = 1500
        };
        
        _port.Open();
        _running = true;
        _readThread = new Thread(ReadLoop) { IsBackground = true };
        _readThread.Start();
    }

    private void ReadLoop() {
        byte[] buffer = new byte[1024];
        while (_running) {
            try {
                int bytesRead = _port.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0) {
                    byte[] data = new byte[bytesRead];
                    Buffer.BlockCopy(buffer, 0, data, 0, bytesRead);
                    OnDataReceived?.Invoke(data);
                }
            }
            catch (TimeoutException) {
                // 预期内的超时忽略
            }
            catch (Exception ex) {
                OnError?.Invoke(ex);
            }
        }
    }

    public void SendModbusCommand(byte deviceId, byte functionCode, ushort address) {
        byte[] frame = new byte[8];
        frame[0] = deviceId;           // 设备地址
        frame[1] = functionCode;       // 功能码
        frame[2] = (byte)(address >> 8); // 寄存器地址高字节
        frame[3] = (byte)address;        // 寄存器地址低字节
        frame[4] = 0x00;                // 长度高字节
        frame[5] = 0x02;                // 长度低字节(读取2个寄存器)
        
        // 计算CRC16校验
        ushort crc = CalculateModbusCRC(frame, 0, 6);
        frame[6] = (byte)crc;
        frame[7] = (byte)(crc >> 8);
        
        _port.Write(frame, 0, 8);
    }

    public void Disconnect() {
        _running = false;
        Thread.Sleep(100); // 给读取线程退出时间
        if (_port.IsOpen) _port.Close();
    }

    // CRC16计算算法
    private ushort CalculateModbusCRC(byte[] data, int offset, int length) {
        ushort crc = 0xFFFF;
        for (int pos = offset; pos < offset + length; pos++) {
            crc ^= data[pos];
            for (int i = 8; i != 0; i--) {
                if ((crc & 0x0001) != 0) {
                    crc >>= 1;
                    crc ^= 0xA001;
                }
                else crc >>= 1;
            }
        }
        return crc;
    }

    public event Action<byte[]> OnDataReceived;
    public event Action<Exception> OnError;
}

工业通信关键要点:

  1. 电磁干扰(EMI)防护
  • 使用双绞屏蔽线连接(CAT5e以上)
  • 接口端加磁环抑制高频噪声
  • 机箱外壳接地电阻<4Ω
  1. 信号衰减处理

电缆类型

最大传输距离(9600bps)

CAT5e

1200m

CAT6

1800m

RS232

15m

3.2 USB控制与HID设备

3.2.1 HID设备通信架构

classDiagram
    class HIDDevice {
        +VendorID : int
        +ProductID : int
        +DevicePath : string
        +Open() bool
        +Write(byte[] data) int
        +Read(byte[] buffer) int
        +Close()
    }

C# HID通信实现:

using System;
using System.Runtime.InteropServices;

public class HIDDevice {
    private IntPtr _deviceHandle = IntPtr.Zero;

    [DllImport("hid.dll", SetLastError = true)]
    private static extern bool HidD_GetHidGuid(out Guid hidGuid);
    
    [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SetupDiGetClassDevs(
        ref Guid classGuid, IntPtr enumerator, IntPtr hwndParent, int flags);
    
    public bool Open(int vid, int pid) {
        // 获取HID接口GUID
        Guid hidGuid;
        HidD_GetHidGuid(out hidGuid);
        
        // 枚举设备
        IntPtr deviceInfoSet = SetupDiGetClassDevs(
            ref hidGuid, IntPtr.Zero, IntPtr.Zero, 
            DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        
        // 遍历设备逻辑...
        // 此处简化实现逻辑
        return true;
    }

    public int Write(byte[] data) {
        // 使用CreateFile和WriteFile API实现
        // 实际代码需处理同步/异步模式
        return data.Length;
    }

    private const int DIGCF_PRESENT = 0x0002;
    private const int DIGCF_DEVICEINTERFACE = 0x0010;
}

USB协议栈分析

应用层: 自定义指令
↑
HID层: 报告描述符
↑
USB设备类: HID规范
↑
端点管道: 控制/中断传输
↑
物理层: USB2.0/3.0

3.3 NI-VISA高级控制技巧

3.3.1 波形数据捕获优化

using Ivi.Visa;
using NationalInstruments.Visa;

public class OscilloscopeController {
    private MessageBasedSession _session;
    
    public double[] CaptureWaveform(string resourceName, int channel = 1) {
        _session = (MessageBasedSession)ResourceManager.GetSession(resourceName);
        
        // 配置高分辨率捕获
        _session.RawIO.Write(":WAV:POIN:MODE RAW\n");
        _session.RawIO.Write($":WAV:SOUR CHAN{channel}\n");
        _session.RawIO.Write(":WAV:FORM BYTE\n"); // 使用8位数据节省带宽
        
        // 触发单次采集
        _session.RawIO.Write(":SING\n");
        Thread.Sleep(100); // 等待触发
        
        // 获取波形数据
        _session.RawIO.Write(":WAV:DATA?\n");
        byte[] binData = _session.RawIO.Read(); // 自动处理二进制块
        
        // 解析波形数据(8位无符号格式)
        double[] voltages = new double[binData.Length];
        for (int i = 0; i < binData.Length; i++) {
            voltages[i] = (binData[i] - 128) * _vPerDivision / 25.0;
        }
        return voltages;
    }
    
    private double _vPerDivision = 0.1; // 垂直灵敏度
}

VISA性能提升关键

  1. 二进制传输
  • ASCII传输1000点需10ms,二进制仅需1ms
  • 使用:WAV:FORM WORD减少转换损耗
  1. 块传输优化

// 设置最大传输块大小
_session.RawIO.BufferSize = 1024 * 1024; // 1MB

  1. 快速查询技术

// 避免无效等待
if (_session.BytesAvailable > 0) {
    return _session.ReadString();
}

3.4 NI-DAQmx数据采集

3.4.1 多通道同步采样

using NationalInstruments.DAQmx;

public class MultichannelAcquisition {
    private Task _task;
    private AnalogMultiChannelReader _reader;
    
    public void StartAcquisition(int sampleRate, int samplesPerChannel) {
        _task = new Task();
        
        // 添加电压输入通道(差分模式)
        _task.AIChannels.CreateVoltageChannel("Dev1/ai0", "Ch0",
            AITerminalConfiguration.Differential, -10, 10, AIVoltageUnits.Volts);
        _task.AIChannels.CreateVoltageChannel("Dev1/ai1", "Ch1",
            AITerminalConfiguration.Differential, -5, 5, AIVoltageUnits.Volts);
        
        // 配置定时引擎
        _task.Timing.ConfigureSampleClock(
            "", sampleRate, SampleClockActiveEdge.Rising,
            SampleQuantityMode.FiniteSamples, samplesPerChannel);
            
        // 使用DMA传输
        _task.Stream.InputBufferSize = sampleRate * 2; // 双缓冲
        _task.Control(TaskAction.Verify);
        
        // 注册数据处理事件
        _task.EveryNSamplesRead += OnSamplesAcquired;
        _task.Done += OnAcquisitionComplete;
        
        // 启动任务
        _reader = new AnalogMultiChannelReader(_task.Stream);
        _task.Start();
    }

    private void OnSamplesAcquired(object sender, EveryNSamplesReadEventArgs e) {
        double[,] data = _reader.ReadMultiSample(e.SampleCount);
        // data[0, i] - 通道0数据
        // data[1, i] - 通道1数据
    }
}

采集性能关键参数

参数

典型值

影响范围

ADC采样率

250 kS/s

信号带宽限制

输入阻抗

10 GΩ

高阻信号测量精度

输入偏置电流

0.2 nA

小电流测量精度

通道间串扰

< -100 dB

多通道隔离度

3.5 硬件安全控制设计

3.5.1 五级安全保护模型

public class HardwareSafetySystem {
    // 1. 电路保护级
    private OvercurrentProtector _hardwareOCP = new OvercurrentProtector();
    
    // 2. 驱动控制级
    public void EnablePower(bool enable) {
        if (MonitorTemperature() > 85.0) {
            throw new ThermalRunawayException("温度超标禁止启动");
        }
        _driverIC.SetEnable(enable);
    }
    
    // 3. 软件逻辑级
    private void CheckSafetyConstraints() {
        if (_voltage > 32.0 || _current > 5.0) {
            EmergencyShutdown();
        }
    }
    
    // 4. 监控系统级
    private async void StartSafetyMonitor() {
        while (_isRunning) {
            await Task.Delay(100);
            if (!_safetyBoard.ResponseReceived) {
                EmergencyShutdown();
            }
        }
    }
    
    // 5. 物理隔离级
    [DllImport("user32.dll")]
    public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
    
    public void PressEmergencyKey() {
        keybd_event(0x13, 0, 0, UIntPtr.Zero); // 模拟按下PAUSE键
    }
}

安全逻辑真值表

温度(°C)

电流(A)

电压(V)

动作

<80

<4.0

<30

正常运行

80-90

任意

任意

降功率

>90

任意

任意

紧急停机

任意

>4.5

任意

限流保护

任意

任意

>32.0

跳闸断电

3.6 高速数据流处理

3.7.1 实时DSP处理框架

using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;

public class RealTimeDspProcessor {
    private double[] _circularBuffer;
    private int _bufferIndex;
    
    public RealTimeDspProcessor(int size) {
        _circularBuffer = new double[size];
    }
    
    public void ProcessSample(double sample) {
        // 写入循环缓冲区
        _circularBuffer[_bufferIndex] = sample;
        _bufferIndex = (_bufferIndex + 1) % _circularBuffer.Length;
        
        // 每1024点执行FFT
        if (_bufferIndex % 1024 == 0) {
            double[] segment = new double[1024];
            Array.Copy(_circularBuffer, _bufferIndex, segment, 0, 1024);
            Array.ConstrainedCopy(_circularBuffer, 0, 
                segment, 1024 - _bufferIndex, _bufferIndex);
            
            // 应用汉宁窗
            double[] window = Window.Hann(1024);
            for (int i = 0; i < 1024; i++) {
                segment[i] *= window[i];
            }
            
            // 执行FFT
            Complex[] spectrum = new Complex[1024];
            for (int i = 0; i < 1024; i++) {
                spectrum[i] = new Complex(segment[i], 0);
            }
            Fourier.Forward(spectrum);
            
            // 分析频谱...
        }
    }
    
    public IEnumerable<double> MovingMedianFilter(int windowSize) {
        for (int i = 0; i < _circularBuffer.Length - windowSize; i++) {
            double[] window = new double[windowSize];
            Array.Copy(_circularBuffer, i, window, 0, windowSize);
            Array.Sort(window);
            yield return window[windowSize / 2]; // 中位数值
        }
    }
}

处理性能对比

算法

10000点处理时间

适用场景

滑动平均

0.8 ms

低频慢变信号

FIR滤波

2.5 ms

精确频率选择

IIR滤波

1.2 ms

实时控制

FFT分析

4.7 ms

频谱特征提取

实战项目:电池充放电测试系统

硬件组成:

  • Keithley 2450源表(充放电控制)
  • NI 9229高精度采集卡(电压/电流监测)
  • ESP32温控模块(温度监控)
  • 工业安全继电器(过压保护)

软件架构:

public class BatteryTester {
    private SourceMeter _source;
    private DaqDevice _daq;
    private TemperatureMonitor _tempMonitor;
    private SafetyRelay _relay;
    
    public TestResult RunChargeTest() {
        // 初始化安全系统
        _relay.SetEnable(false); // 断开主回路
        _tempMonitor.Start();
        
        // 充电曲线参数
        double[] voltageStages = { 3.0, 3.8, 4.2 };
        double[] currentLimits = { 1.0, 0.5, 0.1 };
        
        // 分阶段充电
        for (int stage = 0; stage < voltageStages.Length; stage++) {
            _source.ApplyVoltage(voltageStages[stage]);
            _source.SetCurrentLimit(currentLimits[stage]);
            _relay.SetEnable(true); // 接通回路
            
            while (true) {
                BatteryStatus status = ReadBatteryStatus();
                
                // 安全保护检查
                if (status.Temperature > 50.0 || status.Voltage > 4.25) {
                    AbortTest();
                    return TestResult.Failed("温度或电压超标");
                }
                
                // 充电完成条件
                if (Math.Abs(status.Current) < 0.01 * currentLimits[stage]) {
                    break;
                }
                
                Thread.Sleep(1000);
            }
        }
        
        _relay.SetEnable(false);
        return TestResult.Success();
    }
    
    private BatteryStatus ReadBatteryStatus() {
        double voltage = _daq.ReadAnalog(0);     // 通道0:电池电压
        double current = _source.MeasureCurrent(); // 源表电流测量
        double temp = _tempMonitor.ReadCelsius();
        return new BatteryStatus(voltage, current, temp);
    }
}

校准与验证:

  1. 电压校准

public void CalibrateVoltage(double knownVoltage) {
    double rawValue = _daq.ReadAnalog(0);
    double factor = knownVoltage / rawValue;
    SaveCalibrationFactor(0, factor);
}

  1. 温度补偿

public double GetCompensatedVoltage() {
    double rawVoltage = ReadAnalog(0);
    double temp = _tempMonitor.ReadCelsius();
    double tempCoeff = GetCalibrationData().TempCoeff; // 温度系数
    return rawVoltage * (1 + (25.0 - temp) * tempCoeff);
}

关键知识总结

  1. 硬件交互三原则
  • 确定性:精确控制时序(使用高精度定时器)
  • 鲁棒性:双通道信号校验+超时处理
  • 安全性:硬件级+软件级双重保护
  1. 调试黑盒工具
  • USB协议分析仪(Saleae Logic Pro 16)
  • 串口数据记录器(Advanced Serial Port Logger)
  • VISA调试助手(NI-VISA Interactive Control)
  1. 进阶学习资源
  • 《C#硬件编程权威指南》(James McCaffrey)
  • Keithley《SourceMeter 2450编程手册》
  • NI开发者专区:ni.com/developer

本教程涵盖40+个核心技术要点,结合工业级案例代码与实践经验,建立完整的C#硬件集成开发知识体系。后续可拓展学习FPGA协同处理、实时操作系统集成等高阶主题。

举报

相关推荐

0 条评论