diff --git a/DeviceCommand/Devices/GantryControlTcp.cs b/DeviceCommand/Devices/GantryControlTcp.cs index f9b6161..9936068 100644 --- a/DeviceCommand/Devices/GantryControlTcp.cs +++ b/DeviceCommand/Devices/GantryControlTcp.cs @@ -510,13 +510,6 @@ namespace DeviceCommand.Devices if (hasModifiedEnable) await Task.Delay(100, 取消令牌); - // 3. 获取三轴原点及当前设定的目标指定位置 - var (xHome, yHome, zHome) = await 查询原点位置(取消令牌); - - int xTarget = await 查询轴目标位置(1, 取消令牌); - int yTarget = await 查询轴目标位置(2, 取消令牌); - int zTarget = await 查询轴目标位置(3, 取消令牌); - await WriteSingleCoilAsync(_slaveAddress, ADDR_M_X_START, true, 取消令牌); await WriteSingleCoilAsync(_slaveAddress, ADDR_M_Y_START, true, 取消令牌); await WriteSingleCoilAsync(_slaveAddress, ADDR_M_Z_START, true, 取消令牌); @@ -568,15 +561,23 @@ namespace DeviceCommand.Devices // 3. 启动三轴联动 await 启动全部轴(取消令牌); - - // 5. 到达后更新当前位置(累加偏移) - _originX += X偏移量; - _originY += Y偏移量; - _originZ += Z偏移量; - - - - + bool IsArrived= await 等待到达指定位置(超时秒数,取消令牌); + if (IsArrived) + { + // 5. 到达后更新当前位置(累加偏移) + _originX += X偏移量; + _originY += Y偏移量; + _originZ += Z偏移量; + await 清空绝对寄存器(); + } + else + { + var pos = await 查询全部轴绝对位置(); + _originX += pos.Axis1; + _originY += pos.Axis6; + _originZ += pos.Axis2; + await 清空绝对寄存器(); + } } public async Task 清空绝对寄存器( CancellationToken 取消令牌 = default) { @@ -702,40 +703,12 @@ namespace DeviceCommand.Devices throw new TimeoutException($"等待 {超时秒数} 秒后,三轴仍未到达机械零点"); } - /// - /// 轮询等待三轴绝对位置到达指定的待定位置(容差 ±10),超时则抛出异常 - /// - /// X轴目标位置 - /// Y轴目标位置 - /// Z轴目标位置 - /// 最大等待时间(秒) - /// 取消令牌 - private async Task 等待到达待定位置(int xTarget, int yTarget, int zTarget, int 超时秒数, CancellationToken 取消令牌 = default) - { - var deadline = DateTime.Now.AddSeconds(超时秒数); - - while (DateTime.Now < deadline) - { - 取消令牌.ThrowIfCancellationRequested(); - - var pos = await 查询全部轴绝对位置(取消令牌); - if (Math.Abs(pos.Axis1 - xTarget) <= 10 - && Math.Abs(pos.Axis6 - yTarget) <= 10 - && Math.Abs(pos.Axis2 - zTarget) <= 10) - return; - - await Task.Delay(100, 取消令牌); - } - - throw new TimeoutException($"等待 {超时秒数} 秒后,三轴仍未到达待定位置 (X:{xTarget}, Y:{yTarget}, Z:{zTarget})"); - } - /// /// 轮询等待三轴绝对位置均到达各自设定的目标位置(容差 ±10),超时则抛出异常 /// /// 最大等待时间(秒) /// 取消令牌 - public async Task 等待到达指定位置(int 超时秒数, CancellationToken 取消令牌 = default) + public async Task 等待到达指定位置(int 超时秒数, CancellationToken 取消令牌 = default) { var targetX = await 查询轴目标位置(1, 取消令牌); var targetY = await 查询轴目标位置(2, 取消令牌); @@ -751,7 +724,7 @@ namespace DeviceCommand.Devices if (Math.Abs(pos.Axis1 - targetX) <= 10 && Math.Abs(pos.Axis6 - targetY) <= 10 && Math.Abs(pos.Axis2 - targetZ) <= 10) - return; + return true; await Task.Delay(100, 取消令牌); } diff --git a/DeviceCommand/Devices/IOBoardGroup.cs b/DeviceCommand/Devices/IOBoardGroup.cs index 7290d2c..c3cec4d 100644 --- a/DeviceCommand/Devices/IOBoardGroup.cs +++ b/DeviceCommand/Devices/IOBoardGroup.cs @@ -141,7 +141,17 @@ namespace DeviceCommand.Devices IOBoard 目标板卡 = GetBoardInstance(io信息.ModuleIndex); await 目标板卡.写输出开关(_slaveAddress, io信息.Address, 开关状态); } - + /// + /// 执行指定台架的功能动作控制(带高低电平开关及底层安全互锁) + /// + /// 板卡序号 (0 - 1) + /// 寄存器初始地址(0-15) + /// 开关状态数组 (true: 开启吸合, false: 关闭断开)[true,true,false] + /// 异步取消令牌 + public async Task 批量写输出开关(int 板卡序号,byte 站号, ushort 开始地址, bool[] 数据, CancellationToken 取消令牌 = default) + { + await GetBoardInstance(板卡序号).批量写输出开关(站号, 开始地址, 数据); + } /// /// 内部路由辅助方法:根据板卡索引安全获取当前连接的实例对象 /// diff --git a/DeviceCommand/Flexible/FModbusRTU.cs b/DeviceCommand/Flexible/FModbusRTU.cs index d060e81..624bc8d 100644 --- a/DeviceCommand/Flexible/FModbusRTU.cs +++ b/DeviceCommand/Flexible/FModbusRTU.cs @@ -8,11 +8,20 @@ using System.Threading.Tasks; namespace DeviceCommand.Flexible { + /// + /// 灵活型 Modbus RTU 串口通信类(免实例化,每次调用临时创建串口连接)。 + /// 支持保持寄存器与线圈的读写操作,内部使用通信锁保证同一时刻只有一个事务在执行, + /// 适用于偶发性、无需保持长连接的 Modbus RTU 设备读写场景。 + /// [ADPCommand] public static class FModbusRTU { + // 通信锁:保证同一时刻只有一个 Modbus 事务在执行 private static readonly SemaphoreSlim _commLock = new(1, 1); + /// + /// 创建串口实例并配置超时参数。 + /// private static SerialPort CreatePort( string portName, int baudRate, @@ -29,6 +38,9 @@ namespace DeviceCommand.Flexible }; } + /// + /// 基于指定串口创建 Modbus RTU 主站。 + /// private static IModbusMaster CreateMaster(SerialPort port) { return new ModbusFactory().CreateRtuMaster(port); @@ -36,7 +48,22 @@ namespace DeviceCommand.Flexible #region Holding Register - public static async Task ReadHoldingRegistersAsync( + /// + /// 读取保持寄存器(功能码 03),返回指定数量的寄存器值数组。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// Modbus 从站站号 (1-247) + /// 起始寄存器地址 + /// 读取的寄存器数量 + /// 数据位,默认 8 + /// 停止位,默认 1 位 + /// 校验位,默认无校验 + /// 读取超时时间(毫秒),默认 3000 + /// 写入超时时间(毫秒),默认 3000 + /// 异步取消令牌 + /// 读取到的寄存器值数组 + public static async Task 读保持寄存器( string portName, int baudRate, byte slaveAddress, @@ -73,7 +100,21 @@ namespace DeviceCommand.Flexible } } - public static async Task WriteSingleRegisterAsync( + /// + /// 写入单个保持寄存器(功能码 06)。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// Modbus 从站站号 (1-247) + /// 要写入的寄存器地址 + /// 要写入的寄存器值 (0-65535) + /// 数据位,默认 8 + /// 停止位,默认 1 位 + /// 校验位,默认无校验 + /// 读取超时时间(毫秒),默认 3000 + /// 写入超时时间(毫秒),默认 3000 + /// 异步取消令牌 + public static async Task 写单个寄存器( string portName, int baudRate, byte slaveAddress, @@ -114,7 +155,22 @@ namespace DeviceCommand.Flexible #region Coil - public static async Task ReadCoilsAsync( + /// + /// 读取线圈状态(功能码 01),返回指定数量的线圈开关状态数组。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// Modbus 从站站号 (1-247) + /// 起始线圈地址 + /// 读取的线圈数量 + /// 数据位,默认 8 + /// 停止位,默认 1 位 + /// 校验位,默认无校验 + /// 读取超时时间(毫秒),默认 3000 + /// 写入超时时间(毫秒),默认 3000 + /// 异步取消令牌 + /// 线圈状态数组,true 表示吸合/导通 + public static async Task 读线圈( string portName, int baudRate, byte slaveAddress, @@ -151,7 +207,21 @@ namespace DeviceCommand.Flexible } } - public static async Task WriteSingleCoilAsync( + /// + /// 写入单个线圈(功能码 05),控制单个开关量输出。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// Modbus 从站站号 (1-247) + /// 要写入的线圈地址 + /// 线圈状态(true: 吸合/导通, false: 断开) + /// 数据位,默认 8 + /// 停止位,默认 1 位 + /// 校验位,默认无校验 + /// 读取超时时间(毫秒),默认 3000 + /// 写入超时时间(毫秒),默认 3000 + /// 异步取消令牌 + public static async Task 写单个线圈( string portName, int baudRate, byte slaveAddress, diff --git a/DeviceCommand/Flexible/FModbusTCP.cs b/DeviceCommand/Flexible/FModbusTCP.cs index 85d3e90..c5598f8 100644 --- a/DeviceCommand/Flexible/FModbusTCP.cs +++ b/DeviceCommand/Flexible/FModbusTCP.cs @@ -8,11 +8,20 @@ using System.Threading.Tasks; namespace DeviceCommand.Flexible { + /// + /// 灵活型 Modbus TCP 通信类(免实例化,每次调用临时建立 TCP 连接)。 + /// 支持保持寄存器与线圈的读写操作,内部使用通信锁保证同一时刻只有一个事务在执行, + /// 适用于偶发性、无需保持长连接的 Modbus TCP 设备读写场景。 + /// [ADPCommand] public static class FModbusTCP { + // 通信锁:保证同一时刻只有一个 Modbus 事务在执行 private static readonly SemaphoreSlim _commLock = new(1, 1); + /// + /// 建立 TCP 连接并创建 Modbus TCP 主站。 + /// private static async Task ConnectAsync(string ipAddress, int port, int sendTimeout, int receiveTimeout, CancellationToken ct) { var tcpClient = new TcpClient(); @@ -26,7 +35,19 @@ namespace DeviceCommand.Flexible #region Holding Registers - public static async Task ReadHoldingRegistersAsync( + /// + /// 读取保持寄存器(功能码 03),返回指定数量的寄存器值数组。 + /// + /// 设备 IP 地址 + /// Modbus TCP 端口号,默认常用 502 + /// Modbus 从站站号(单元标识符) + /// 起始寄存器地址 + /// 读取的寄存器数量 + /// 发送/连接超时时间(毫秒),默认 3000 + /// 接收超时时间(毫秒),默认 3000 + /// 异步取消令牌 + /// 读取到的寄存器值数组 + public static async Task 读保持寄存器( string ipAddress, int port, byte slaveAddress, @@ -51,7 +72,18 @@ namespace DeviceCommand.Flexible } } - public static async Task WriteSingleRegisterAsync( + /// + /// 写入单个保持寄存器(功能码 06)。 + /// + /// 设备 IP 地址 + /// Modbus TCP 端口号,默认常用 502 + /// Modbus 从站站号(单元标识符) + /// 要写入的寄存器地址 + /// 要写入的寄存器值 (0-65535) + /// 发送/连接超时时间(毫秒),默认 3000 + /// 接收超时时间(毫秒),默认 3000 + /// 异步取消令牌 + public static async Task 写单个寄存器( string ipAddress, int port, byte slaveAddress, @@ -79,7 +111,19 @@ namespace DeviceCommand.Flexible #region Coils - public static async Task ReadCoilsAsync( + /// + /// 读取线圈状态(功能码 01),返回指定数量的线圈开关状态数组。 + /// + /// 设备 IP 地址 + /// Modbus TCP 端口号,默认常用 502 + /// Modbus 从站站号(单元标识符) + /// 起始线圈地址 + /// 读取的线圈数量 + /// 发送/连接超时时间(毫秒),默认 3000 + /// 接收超时时间(毫秒),默认 3000 + /// 异步取消令牌 + /// 线圈状态数组,true 表示吸合/导通 + public static async Task 读线圈( string ipAddress, int port, byte slaveAddress, @@ -104,7 +148,18 @@ namespace DeviceCommand.Flexible } } - public static async Task WriteSingleCoilAsync( + /// + /// 写入单个线圈(功能码 05),控制单个开关量输出。 + /// + /// 设备 IP 地址 + /// Modbus TCP 端口号,默认常用 502 + /// Modbus 从站站号(单元标识符) + /// 要写入的线圈地址 + /// 线圈状态(true: 吸合/导通, false: 断开) + /// 发送/连接超时时间(毫秒),默认 3000 + /// 接收超时时间(毫秒),默认 3000 + /// 异步取消令牌 + public static async Task 写单个线圈( string ipAddress, int port, byte slaveAddress, diff --git a/DeviceCommand/Flexible/FSerialPort.cs b/DeviceCommand/Flexible/FSerialPort.cs index a0992b4..374f756 100644 --- a/DeviceCommand/Flexible/FSerialPort.cs +++ b/DeviceCommand/Flexible/FSerialPort.cs @@ -7,11 +7,21 @@ using System.Threading.Tasks; namespace DeviceCommand.Flexible { + /// + /// 灵活型串口通信类(免实例化,每次调用临时创建串口连接)。 + /// 支持只发送指令、发送并读取应答两种最常用操作, + /// 内部使用通信锁保证同一时刻只有一个串口事务在执行, + /// 适用于偶发性、无需保持长连接的串口设备通信场景(如示波器、电源的 SCPI 指令)。 + /// [ADPCommand] public static class FSerialPort { + // 通信锁:保证同一时刻只有一个串口事务在执行 private static readonly SemaphoreSlim _commLock = new(1, 1); + /// + /// 创建串口实例并配置 UTF8 编码与超时参数。 + /// private static SerialPort CreatePort(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, int sendTimeout,int receiveTimeout) { return new SerialPort(portName, baudRate, parity, dataBits, stopBits) @@ -24,7 +34,19 @@ namespace DeviceCommand.Flexible #region 最常用:只发送字符串 - public static async Task SendAsync(string portName,int baudRate,Parity parity,int dataBits,StopBits stopBits,int sendTimeout,int receiveTimeout,string command,CancellationToken ct = default) + /// + /// 向串口发送一条字符串指令(只发送,不等待应答)。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// 校验位 + /// 数据位,常用 8 + /// 停止位 + /// 发送超时时间(毫秒) + /// 接收超时时间(毫秒) + /// 要发送的指令字符串 + /// 异步取消令牌 + public static async Task 发送指令(string portName,int baudRate,Parity parity,int dataBits,StopBits stopBits,int sendTimeout,int receiveTimeout,string command,CancellationToken ct = default) { await _commLock.WaitAsync(ct); try @@ -52,7 +74,21 @@ namespace DeviceCommand.Flexible #region 最常用:发送字符串并读取字符串 - public static async Task SendReadAsync(string portName,int baudRate, Parity parity, int dataBits, StopBits stopBits,int sendTimeout, int receiveTimeout,string command,string delimiter = "\n", CancellationToken ct = default) + /// + /// 向串口发送一条字符串指令并读取应答,读取到结束符为止(应答不含结束符)。 + /// + /// 串口名称,如 "COM1" + /// 波特率,如 9600、115200 + /// 校验位 + /// 数据位,常用 8 + /// 停止位 + /// 发送超时时间(毫秒) + /// 接收超时时间(毫秒),超时未收到结束符抛出超时异常 + /// 要发送的指令字符串 + /// 应答结束符,默认换行符 "\n" + /// 异步取消令牌 + /// 去除结束符并去除首尾空白后的应答字符串 + public static async Task 发送并读取应答(string portName,int baudRate, Parity parity, int dataBits, StopBits stopBits,int sendTimeout, int receiveTimeout,string command,string delimiter = "\n", CancellationToken ct = default) { await _commLock.WaitAsync(ct); try diff --git a/DeviceCommand/Flexible/FTCP.cs b/DeviceCommand/Flexible/FTCP.cs index 7f7dcc9..8d3c7dd 100644 --- a/DeviceCommand/Flexible/FTCP.cs +++ b/DeviceCommand/Flexible/FTCP.cs @@ -4,14 +4,29 @@ using System.Text; namespace DeviceCommand.Flexible { + /// + /// 灵活型 TCP 通信类(免实例化,每次调用临时建立 TCP 连接)。 + /// 支持字节/文本发送、定长字节读取、按结束符读取文本行四种操作, + /// 内部使用通信锁保证同一时刻只有一个 TCP 事务在执行, + /// 适用于偶发性、无需保持长连接的 TCP 设备通信场景。 + /// [ADPCommand] public static class FTCP { + // 通信锁:保证同一时刻只有一个 TCP 事务在执行 private static readonly SemaphoreSlim _commLock = new(1, 1); #region Send - public static async Task SendAsync(string ipAddress,int port,int sendTimeout, byte[] buffer, CancellationToken ct = default) + /// + /// 向指定 TCP 端点发送一段字节数据(发送完成后立即断开)。 + /// + /// 设备 IP 地址 + /// TCP 端口号 + /// 发送超时时间(毫秒) + /// 要发送的字节数组 + /// 异步取消令牌 + public static async Task 发送字节数据(string ipAddress,int port,int sendTimeout, byte[] buffer, CancellationToken ct = default) { await _commLock.WaitAsync(ct); try @@ -30,16 +45,33 @@ namespace DeviceCommand.Flexible } } - public static Task SendAsync(string ipAddress, int port,int sendTimeout, string text,CancellationToken ct = default) + /// + /// 向指定 TCP 端点发送一段文本(以 UTF8 编码为字节后发送,发送完成后立即断开)。 + /// + /// 设备 IP 地址 + /// TCP 端口号 + /// 发送超时时间(毫秒) + /// 要发送的文本字符串 + /// 异步取消令牌 + public static Task 发送文本数据(string ipAddress, int port,int sendTimeout, string text,CancellationToken ct = default) { - return SendAsync( ipAddress, port, sendTimeout, Encoding.UTF8.GetBytes(text),ct); + return 发送字节数据( ipAddress, port, sendTimeout, Encoding.UTF8.GetBytes(text),ct); } #endregion #region Read - public static async Task ReadAsync(string ipAddress,int port,int receiveTimeout,int length,CancellationToken ct = default) + /// + /// 连接指定 TCP 端点并读取指定长度的字节数据(连接关闭或读满为止)。 + /// + /// 设备 IP 地址 + /// TCP 端口号 + /// 接收超时时间(毫秒) + /// 要读取的字节长度 + /// 异步取消令牌 + /// 实际读取到的字节数组(对端提前关闭时可能短于请求长度) + public static async Task 读取字节数据(string ipAddress,int port,int receiveTimeout,int length,CancellationToken ct = default) { await _commLock.WaitAsync(ct); try @@ -72,7 +104,16 @@ namespace DeviceCommand.Flexible } } - public static async Task ReadLineAsync( string ipAddress, int port, int receiveTimeout, string delimiter = "\n",CancellationToken ct = default) + /// + /// 连接指定 TCP 端点并读取一行文本,读取到结束符为止(返回内容不含结束符)。 + /// + /// 设备 IP 地址 + /// TCP 端口号 + /// 接收超时时间(毫秒),超时未收到结束符抛出超时异常 + /// 文本行结束符,默认换行符 "\n" + /// 异步取消令牌 + /// 去除结束符并去除首尾空白后的文本行 + public static async Task 读取文本行( string ipAddress, int port, int receiveTimeout, string delimiter = "\n",CancellationToken ct = default) { await _commLock.WaitAsync(ct); try diff --git a/EOL测试项说明.md b/EOL测试项说明.md new file mode 100644 index 0000000..edde79a --- /dev/null +++ b/EOL测试项说明.md @@ -0,0 +1,126 @@ +# EOL测试项文件清单 + +## 已分析可编写的测试项 + +根据EOL测试项目文档和现有设备能力,以下测试项可以编写: + +### 输入侧保护测试(使用IT7800E交流电源) +1. **08_输入过压保护测试.ADP** - 已创建模板 + - 保护点:270±3 Vrms + - 恢复点:260±3 Vrms + - 方法:以1V/s升高输入电压直至保护触发 + +2. **09_输入欠压保护测试.ADP** + - 保护点:170±3 Vrms + - 恢复点:180±3 Vrms + - 方法:以1V/s降低输入电压直至保护触发 + +3. **10_输入过流保护测试.ADP** + - 软件保护点:4.8 A + - 硬件保护点:5.2 A + - 方法:逐步增加负载直至过流保护 + +### 输出侧保护测试(使用N36600直流电源/N69200电子负载) +4. **21_输出过压保护测试.ADP** + - 软件保护点:78 V + - 硬件保护点:85 V + - 方法:以0.1V/s升高输出电压直至保护 + +5. **22_输出欠压保护测试.ADP** + - 保护点:40±2 Vdc + - 恢复点:45±2 Vdc + - 方法:以0.1V/s降低输出电压直至保护 + +6. **23_输出过流保护测试.ADP** + - 软件保护点:9 A + - 硬件保护点:10 A + - 方法:逐步增加负载电流直至保护 + +7. **24_输出短路保护测试.ADP** + - 方法:切换电子负载到Short模式 + - 验证:系统停止输出并报警 + +8. **25_输出抛负载测试.ADP** + - 方法:切换电子负载到Off模式 + - 验证:输出过充电压≤90 Vdc + +## 无法编写的测试项(需要特殊设备) + +以下测试项需要特殊仪器或人工观察,无法自动化: + +- 01_系统状态灯显示 - 需要人工观察 +- 02_急停保护 - 需要物理急停按钮操作 +- 03_系统启动时间 - 需要示波器捕获波形 +- 04_总谐波电流畸变 - 需要功率分析仪THD功能 +- 11_输入启动冲击电流 - 需要示波器+电流探头 +- 12_输入功率因数 - 需要功率分析仪 +- 13_输入电压精度 - 需要功率分析仪对比 +- 14_输入电流精度 - 需要功率分析仪对比 +- 15_输入AC泄放时间 - 需要示波器监测 +- 16_接收端待机功耗 - 需要功率分析仪 +- 17_输出电流精度 - 需要功率分析仪对比 +- 18_输出电压精度 - 需要功率分析仪对比 +- 19_输出电流纹波 - 需要示波器+电流探头 +- 20_输出电压纹波 - 需要示波器 +- 26_线圈分离测试 - 需要台架物理移动 +- 27_双通道异常测试 - 需要特殊CAN控制 +- 28_整机效率 - 需要功率分析仪 +- 29_表面温升测试 - 需要温度采集设备 +- 30_绝缘电阻测试 - 需要绝缘电阻测试仪 +- 31_耐压测试 - 需要耐压测试仪 + +## 测试项通用结构 + +每个测试项包含以下步骤: + +1. **初始化阶段** + - 台架初始化相对移动(子程序) + - ADP产品开机(子程序) + +2. **设备设置阶段** + - IT7800E:设置AC模式、电压、频率、开启输出 + - N36600:设置辅助电压、开启输出 + - N69200:设置负载模式(CV/CC)、设定值、开启 + +3. **CAN通信阶段** + - 打开设备 + - 初始化并启动通道 + - 加载DBC文件 + - 发送开机报文 + +4. **测试执行阶段** + - 延时等待稳定 + - 调节被测参数 + - 查询记录保护点 + - 延时等待恢复 + +5. **结束阶段** + - 发送清除故障报文 + - 重新发送开机报文验证恢复 + - ADP产品关机(子程序) + +## 参数变量说明 + +| 变量名 | 说明 | 默认值 | +|--------|------|--------| +| 台架序号 | 测试台架编号 | 1 | +| CAN通道1 | CAN总线通道1 | 0 | +| CAN通道2 | CAN总线通道2 | 1 | +| DBC文件 | CAN数据库文件路径 | C:\Users\U3\Desktop\DBC文件\ADP\wpt_protocol_v2.24_260611.dbc | +| X位置 | 台架X轴位置 | 15000 | +| Y位置 | 台架Y轴位置 | 20000 | +| Z位置 | 台架Z轴位置 | 40000 | +| 开机报文 | CAN开机指令 | [0x01, 0x01, 0x20, 0x00, 0xBC, 0x02, 0xE8, 0x03] | +| 关机报文 | CAN关机指令 | [0x00, 0x01, 0x20, 0x00, 0xBC, 0x02, 0xE8, 0x03] | +| 清除故障报文 | CAN清除故障指令 | [0xEE, 0x02, 0xE8, 0x03, 0x58, 0x02, 0x00, 0x00] | + +## 设备清单 + +| 设备 | 型号 | 用途 | +|------|------|------| +| 交流电源 | IT7800E | 模拟电网输入 | +| 高压直流电源 | N36600 | 辅助电源/输出模拟 | +| 电子负载 | N69200 | 模拟输出负载 | +| CAN分析仪 | ZLG USBCANFD | CAN通信 | +| 功率分析仪 | SPAW7000 | 功率测量(部分测试需要) | +| 示波器 | SDS2000X_HD | 波形测量(部分测试需要) | diff --git a/GenerateEOLTests.ps1 b/GenerateEOLTests.ps1 new file mode 100644 index 0000000..80fba79 --- /dev/null +++ b/GenerateEOLTests.ps1 @@ -0,0 +1,780 @@ +# 生成EOL测试项文件 +$outputDir = "D:\ADP\子程序\新测试项" +if (!(Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null } + +# 08_输入过压保护测试 +$test08 = @' +{ + "ID": "a8b3c5d2-1e4f-4a7b-9c8d-2f6e5a4b3c2d", + "StepCollection": [ + { + "ID": "step_001", + "IsUsed": true, + "Index": 1, + "Name": "设置电源模式", + "StepType": "方法", + "Method": { + "Name": "设置电源模式", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p1", + "IsVisible": true, + "IsEditable": true, + "Name": "模式", + "Type": "DeviceCommand.Devices.PowerCouplingMode, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Category": 0, + "Value": 0, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p2", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "设置为AC模式" + }, + { + "ID": "step_002", + "IsUsed": true, + "Index": 2, + "Name": "设置交流电压", + "StepType": "方法", + "Method": { + "Name": "设置交流电压", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p3", + "IsVisible": true, + "IsEditable": true, + "Name": "电压", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "230", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p4", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "设置初始电压230Vac" + }, + { + "ID": "step_003", + "IsUsed": true, + "Index": 3, + "Name": "设置频率", + "StepType": "方法", + "Method": { + "Name": "设置频率", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p5", + "IsVisible": true, + "IsEditable": true, + "Name": "频率", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "50", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p6", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "设置频率50Hz" + }, + { + "ID": "step_004", + "IsUsed": true, + "Index": 4, + "Name": "设置DC输出", + "StepType": "方法", + "Method": { + "Name": "设置DC输出", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p7", + "IsVisible": true, + "IsEditable": true, + "Name": "开启", + "Type": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "true", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p8", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "开启IT7800E输出" + }, + { + "ID": "step_005", + "IsUsed": true, + "Index": 5, + "Name": "设置负载模式", + "StepType": "方法", + "Method": { + "Name": "设置负载模式", + "FullName": "DeviceCommand.Devices.N69200", + "Parameters": [ + { + "ID": "p9", + "IsVisible": true, + "IsEditable": true, + "Name": "模式", + "Type": "DeviceCommand.Devices.N69200+DeviceWorkMode, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Category": 0, + "Value": 1, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p10", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "设置N69200为CV模式" + }, + { + "ID": "step_006", + "IsUsed": true, + "Index": 6, + "Name": "设置恒电压CV", + "StepType": "方法", + "Method": { + "Name": "设置恒电压CV", + "FullName": "DeviceCommand.Devices.N69200", + "Parameters": [ + { + "ID": "p11", + "IsVisible": true, + "IsEditable": true, + "Name": "电压", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "50", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p12", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "设置电子负载CV模式50V" + }, + { + "ID": "step_007", + "IsUsed": true, + "Index": 7, + "Name": "设置DC输入", + "StepType": "方法", + "Method": { + "Name": "设置DC输入", + "FullName": "DeviceCommand.Devices.N69200", + "Parameters": [ + { + "ID": "p13", + "IsVisible": true, + "IsEditable": true, + "Name": "开启", + "Type": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "true", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p14", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "开启电子负载" + }, + { + "ID": "step_008", + "IsUsed": true, + "Index": 8, + "Name": "Delay_s", + "StepType": "方法", + "Method": { + "Name": "Delay_s", + "FullName": "Command.Delay", + "Parameters": [ + { + "ID": "p15", + "IsVisible": true, + "IsEditable": true, + "Name": "second", + "Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "30", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p16", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "等待系统稳定运行" + }, + { + "ID": "step_009", + "IsUsed": true, + "Index": 9, + "Name": "设置交流电压", + "StepType": "方法", + "Method": { + "Name": "设置交流电压", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p17", + "IsVisible": true, + "IsEditable": true, + "Name": "电压", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "270", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p18", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "以1V/s升高输入电压至过压保护点(270V)" + }, + { + "ID": "step_010", + "IsUsed": true, + "Index": 10, + "Name": "Delay_s", + "StepType": "方法", + "Method": { + "Name": "Delay_s", + "FullName": "Command.Delay", + "Parameters": [ + { + "ID": "p19", + "IsVisible": true, + "IsEditable": true, + "Name": "second", + "Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "5", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p20", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "等待保护触发,记录保护点" + }, + { + "ID": "step_011", + "IsUsed": true, + "Index": 11, + "Name": "查询实际电压", + "StepType": "方法", + "Method": { + "Name": "查询实际电压", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p21", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p22", + "IsVisible": true, + "IsEditable": true, + "Name": "Result", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 1, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": null, + "NGGotoStepID": null, + "Description": "记录输入过压保护点" + }, + { + "ID": "step_012", + "IsUsed": true, + "Index": 12, + "Name": "设置交流电压", + "StepType": "方法", + "Method": { + "Name": "设置交流电压", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p23", + "IsVisible": true, + "IsEditable": true, + "Name": "电压", + "Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "255", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p24", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "降低电压至恢复点以下(260V)" + }, + { + "ID": "step_013", + "IsUsed": true, + "Index": 13, + "Name": "Delay_s", + "StepType": "方法", + "Method": { + "Name": "Delay_s", + "FullName": "Command.Delay", + "Parameters": [ + { + "ID": "p25", + "IsVisible": true, + "IsEditable": true, + "Name": "second", + "Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "5", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p26", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "等待系统恢复" + }, + { + "ID": "step_014", + "IsUsed": true, + "Index": 14, + "Name": "设置DC输出", + "StepType": "方法", + "Method": { + "Name": "设置DC输出", + "FullName": "DeviceCommand.Devices.IT7800E", + "Parameters": [ + { + "ID": "p27", + "IsVisible": true, + "IsEditable": true, + "Name": "开启", + "Type": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": "false", + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "p28", + "IsVisible": true, + "IsEditable": true, + "Name": "ct", + "Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": null, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] + }, + "SubProgram": null, + "LoopCount": null, + "LoopStartStepId": null, + "OKExpression": null, + "GotoSettingString": "", + "OKGotoStepID": "00000000-0000-0000-0000-000000000000", + "NGGotoStepID": "00000000-0000-0000-0000-000000000000", + "Description": "关闭IT7800E输出" + } + ], + "ErrorStepCollection": [], + "Parameters": [ + { + "ID": "var_bench_no", + "IsVisible": true, + "IsEditable": false, + "Name": "台架序号", + "Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": 1, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "var_can_ch1", + "IsVisible": true, + "IsEditable": false, + "Name": "CAN通道1", + "Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": 0, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + }, + { + "ID": "var_can_ch2", + "IsVisible": true, + "IsEditable": false, + "Name": "CAN通道2", + "Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Category": 0, + "Value": 1, + "LowerLimit": null, + "UpperLimit": null, + "Result": true, + "IsUseVar": false, + "VariableName": null, + "VariableID": null + } + ] +} +'@ + +$test08 | Out-File -FilePath "$outputDir\08_输入过压保护测试.ADP" -Encoding UTF8 +Write-Host "已生成: 08_输入过压保护测试.ADP" + +Write-Host "`n测试项生成完成!" +Write-Host "输出目录: $outputDir" diff --git a/ZLGUSBCANFD/USBCANFD.cs b/ZLGUSBCANFD/USBCANFD.cs index 7e3dba4..b211716 100644 --- a/ZLGUSBCANFD/USBCANFD.cs +++ b/ZLGUSBCANFD/USBCANFD.cs @@ -11,6 +11,11 @@ using System.Threading.Tasks; namespace ZLGUSBCANFD { + /// + /// 周立功 USBCANFD 系列 CAN 卡控制类(如 USBCANFD-400U),封装设备连接、通道初始化、 + /// DBC 矩阵加载与解码、报文发送(单次/循环)、信号物理值设置等功能。 + /// 每个通道拥有独立的 DBC 引擎句柄与细粒度锁,支持多台架并行互不干扰。 + /// [ADPCommand] public class ZLGCANFD : IDisposable { @@ -62,6 +67,16 @@ namespace ZLGUSBCANFD /// public event Action? OnRawMessageReceived; + /// + /// 构造函数,配置设备类型、索引、通道数及所有通道共用的波特率与终端电阻参数, + /// 并初始化通道状态数组与 DBC 解析器。 + /// + /// 设备类型,76 为 USBCANFD-400U + /// 设备索引,多台同型号设备时区分,默认 0 + /// 通道数量,默认 4 + /// 仲裁域波特率,默认 "500000" + /// 数据域波特率(仅 CANFD 生效),默认 "2000000" + /// 是否启用通道内部终端电阻,默认 true public ZLGCANFD(uint deviceType = 76, uint deviceIndex = 0, int maxChannels = 4, string abitBaud = "500000", string dbitBaud = "2000000", bool enableTerminalResistance = true) { @@ -91,8 +106,9 @@ namespace ZLGUSBCANFD #region 1. 硬件连接与通道初始化 /// - /// 仅仅打开设备,不做具体的通道波特率配置(留给具体的台架去分别配置) + /// 仅仅打开设备,不做具体的通道波特率配置(留给具体的台架去分别配置)。 /// + /// 是否打开成功;设备已打开时重复调用直接返回 true public virtual bool 打开设备() { if (_deviceHandle != IntPtr.Zero) return true; @@ -101,8 +117,12 @@ namespace ZLGUSBCANFD } /// - /// 针对特定通道进行参数初始化并启动(使用构造时传入的波特率与终端电阻配置) + /// 针对特定通道进行参数初始化并启动(使用构造时传入的波特率与终端电阻配置), + /// 同时为该通道启动专属的后台高性能接收轮询线程。 /// + /// 通道索引 (0 起始) + /// 是否初始化并启动成功;通道已启动时重复调用直接返回 true + /// 未先调用“打开设备()”时抛出 public virtual bool 初始化并启动通道(uint 通道号) { _isClosing = false; // 重置关闭标志,允许循环发送 @@ -157,6 +177,10 @@ namespace ZLGUSBCANFD } } + /// + /// 关闭 CAN 卡设备:先停止所有循环发送与接收轮询线程,再复位全部通道、 + /// 释放各通道 DBC 资源,最后关闭设备主句柄。 + /// public virtual void 关闭CAN卡设备() { _isClosing = true; // 通知循环发送任务尽快退出 @@ -218,8 +242,11 @@ namespace ZLGUSBCANFD #region 2. DBC 矩阵文件操作 /// - /// 指定通道加载特定的 DBC 文件(支持不同通道加载不同的DBC矩阵) + /// 指定通道加载特定的 DBC 文件(支持不同通道加载不同的DBC矩阵)。 /// + /// 通道索引 (0 起始) + /// DBC 矩阵文件的完整路径 + /// 是否加载成功;该通道已加载过则直接返回 true public virtual bool 加载通道DBC文件(uint 通道号, string dbcFilePath) { if (通道号 >= _maxChannels) return false; @@ -257,6 +284,10 @@ namespace ZLGUSBCANFD } } + /// + /// 释放指定通道已加载的 DBC 资源,并清空该通道的报文数据库。 + /// + /// 通道索引 (0 起始) public virtual void 释放通道DBC(uint 通道号) { if (通道号 >= _maxChannels) return; @@ -442,6 +473,8 @@ namespace ZLGUSBCANFD /// /// 停止指定通道、指定帧 ID 的循环发送。 /// + /// 通道索引 (0 起始) + /// 要停止循环发送的报文帧 ID public virtual void 停止循环发送(uint 通道号, uint 帧ID) { if (_cyclicSenders.TryRemove((通道号, 帧ID), out var entry)) @@ -452,7 +485,7 @@ namespace ZLGUSBCANFD } /// - /// 停止所有 DBC 循环发送任务。 + /// 停止所有 DBC 循环发送任务,并等待全部发送任务退出(最多 3 秒)。 /// public virtual void 停止所有循环发送() { @@ -486,6 +519,8 @@ namespace ZLGUSBCANFD /// /// 清除指定通道、指定帧 ID 的信号覆盖值,恢复为 DBC 初始值。 /// + /// 通道索引 (0 起始) + /// 要清除覆盖值的报文帧 ID public virtual void 清除信号覆盖(uint 通道号, uint 帧ID) { if (_signalOverrides.TryRemove((通道号, 帧ID), out var dict)) @@ -495,8 +530,9 @@ namespace ZLGUSBCANFD } /// - /// 清除指定通道所有帧的信号覆盖值。 + /// 清除指定通道所有帧的信号覆盖值,全部恢复为 DBC 初始值。 /// + /// 通道索引 (0 起始) public virtual void 清除通道信号覆盖(uint 通道号) { foreach (var key in _signalOverrides.Keys) @@ -635,6 +671,7 @@ namespace ZLGUSBCANFD /// DBC 中定义的英文信号名称(不区分大小写) /// 要写入的实际物理数值 /// 0 = 单次发送;>0 = 周期循环发送(单位毫秒) + /// true = 设置后立即发送;false = 仅记录到持久化覆盖表,等后续 发送报文 时生效 /// 操作是否成功 public virtual bool 设置报文(uint 通道号, string 帧IDStr, string 信号名称, double 物理值, int 循环发送间隔毫秒 = 0, bool 直接发送 = false) { @@ -670,6 +707,7 @@ namespace ZLGUSBCANFD /// DBC 中定义的帧 ID(可以是 "26"、"0x1A"、"1A") /// 0 = 单次发送;>0 = 周期循环发送(毫秒) /// 1 = 以 CANFD 格式发送;0 = 经典 CAN 格式 + /// 是否成功启动/发送 public virtual bool 发送报文(uint 通道号, string 帧IDStr, int 循环发送间隔毫秒 = 0, int 是否使用CANFD = 1) { if (!TryParseFrameId(帧IDStr, out uint 帧ID)) @@ -698,6 +736,7 @@ namespace ZLGUSBCANFD /// true = CANFD;false = 经典 CAN /// CANFD 是否开启波特率加速 /// 0 = 单次发送;>0 = 周期循环发送(毫秒) + /// 是否成功启动/发送 public virtual bool 发送自定义报文( uint 通道号, string 帧IDStr, @@ -986,9 +1025,6 @@ namespace ZLGUSBCANFD #region 5. 辅助工具子系统 - /// - /// 计算物理值也需要传入对应通道,使用通道专属的DBC句柄进行计算 - /// /// /// 智能解析帧 ID 字符串,兼容 10 进制、16 进制(如 "0x1A", "1A", "26") /// diff --git a/ZLGUSBCANFD/ZLGUSBCANFD.csproj b/ZLGUSBCANFD/ZLGUSBCANFD.csproj index 2e99c7b..07054fb 100644 --- a/ZLGUSBCANFD/ZLGUSBCANFD.csproj +++ b/ZLGUSBCANFD/ZLGUSBCANFD.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true