using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CCDCount.DLL.CanBus;
namespace CanTest
{
internal class Program
{
static UInt32 m_devtype = 4;//USBCAN2
static UInt32 m_devind = 0;
static UInt32 m_canind = 0;
unsafe static void Main(string[] args)
{
// 示例:运行CANopen主站程序
//RunCanOpenMaster();
ConnectCan();
//SendTest();
//GetTest();
MessageTest();
}
///
/// 运行CANopen主站示例
///
static void RunCanOpenMaster()
{
Console.WriteLine("=== CANopen主站示例 ===\n");
// 创建主站
using (CanOpenMaster master = new CanOpenMaster(4, 0, 0))
{
// 注册事件回调
master.OnTpdoReceived += Master_OnTpdoReceived;
master.OnHeartbeatReceived += Master_OnHeartbeatReceived;
master.OnEmergencyReceived += Master_OnEmergencyReceived;
master.OnLogMessage += Master_OnLogMessage;
// 初始化主站(波特率500kbps)
if (!master.Initialize(CanBaudRate.BaudRate_500K))
{
Console.WriteLine("主站初始化失败!");
return;
}
Console.WriteLine("\n主站初始化成功!\n");
// 方式1: 不使用EDS文件(直接添加节点)
Console.WriteLine("=== 方式1: 不使用EDS文件 ===");
master.AddNode(1, "IO_Module_1");
//master.AddNode(2, "IO_Module_2");
// 方式2: 使用EDS文件(推荐用于第三方设备)
//Console.WriteLine("\n=== 方式2: 使用EDS文件 ===");
//string edsPath1 = @"D:\EDS\servo_drive.eds";
//string edsPath2 = @"D:\EDS\io_module.eds";
// 如果EDS文件存在,加载它们
//if (System.IO.File.Exists(edsPath1))
//{
// master.AddNode(3, "Servo_Drive", edsPath1);
// // 自动配置PDO映射
// master.AutoConfigurePdoFromEds(3);
//}
//else
//{
// master.AddNode(3, "Servo_Drive");
// Console.WriteLine($"EDS文件不存在: {edsPath1}, 使用默认配置");
//}
//if (System.IO.File.Exists(edsPath2))
//{
// master.AddNode(5, "Custom_Device", edsPath2);
// master.AutoConfigurePdoFromEds(5);
//}
//else
//{
// master.AddNode(5, "Custom_Device");
// Console.WriteLine($"EDS文件不存在: {edsPath2}, 使用默认配置");
//}
Console.WriteLine($"\n已添加 {master.NodeIds.Count} 个节点\n");
// 显示EDS信息
foreach (var nodeId in master.NodeIds)
{
var edsInfo = master.GetEdsInfo(nodeId);
if (edsInfo != null)
{
Console.WriteLine($"节点{nodeId}: {edsInfo}");
}
}
Console.WriteLine();
// 等待从站上线
Console.WriteLine("等待从站心跳...\n");
Thread.Sleep(2000);
// 扫描所有节点的设备信息
ScanAllNodes(master);
// 启动所有节点
Console.WriteLine("\n=== 启动所有节点 ===");
master.StartAllNodes();
Thread.Sleep(1000);
// 启用周期性SYNC(10ms周期)
Console.WriteLine("\n=== 启用SYNC ===");
Console.WriteLine("注意: SYNC用于触发从站自动发送TPDO数据");
Console.WriteLine(" RPDO仍可由主站手动发送(事件驱动模式)");
master.EnableSync(10);
// 主循环 - 处理PDO数据
Console.WriteLine("\n=== 进入主循环 (按任意键退出) ===\n");
Console.WriteLine("工作原理:");
Console.WriteLine(" 1. SYNC每10ms发送一次 → 从站自动发送TPDO → OnTpdoReceived事件触发");
Console.WriteLine(" 2. RPDO由主站主动调用SendRpdo()发送(不依赖SYNC)");
Console.WriteLine(" 3. SDO读写用于配置和非实时数据传输\n");
bool running = true;
Task.Run(() =>
{
Console.ReadKey();
running = false;
});
int loopCount = 0;
while (running && master.IsRunning)
{
loopCount++;
// 每100次循环打印一次状态
if (loopCount % 100 == 0)
{
PrintNodeStatus(master);
}
// 示例:定期读取某个节点的SDO数据(非实时配置)
if (loopCount % 500 == 0)
{
ReadNodeParameters(master, 1);
}
// 示例:向节点写入控制命令(SDO方式 - 低速但可靠)
if (loopCount % 1000 == 0)
{
WriteControlCommand(master, 1);
}
// 示例:通过RPDO发送控制数据(PDO方式 - 高速实时控制)
// 注意: 这里的RPDO发送是"事件驱动"模式,不依赖SYNC
// 如果要实现同步RPDO,需要在从站配置RPDO为同步触发类型
if (loopCount % 200 == 0)
{
SendRpdoControl(master, 1);
}
Thread.Sleep(10);
}
// 停止SYNC
master.DisableSync();
// 停止所有节点
Console.WriteLine("\n=== 停止所有节点 ===");
master.StopAllNodes();
Console.WriteLine("\n主站程序结束");
}
}
///
/// 演示如何使用EDS文件的完整示例
///
static void EdsFileUsageExample()
{
Console.WriteLine("=== EDS文件使用示例 ===\n");
using (CanOpenMaster master = new CanOpenMaster(4, 0, 0))
{
master.Initialize(CanBaudRate.BaudRate_500K);
// 场景1: 加载伺服驱动器的EDS文件
Console.WriteLine("场景1: 加载伺服驱动器EDS");
string servoEds = @"C:\Devices\ServoDrive.eds";
if (System.IO.File.Exists(servoEds))
{
master.AddNode(1, "Servo_X", servoEds);
// 查看EDS信息
var edsInfo = master.GetEdsInfo(1);
if (edsInfo != null)
{
Console.WriteLine($" 厂商: {edsInfo.VendorName}");
Console.WriteLine($" 产品: {edsInfo.ProductName}");
Console.WriteLine($" TPDO映射数: {edsInfo.TpdoMappings.Count}");
// 自动配置PDO
master.AutoConfigurePdoFromEds(1);
}
}
else
{
Console.WriteLine(" EDS文件不存在,跳过此场景");
}
// 场景2: 不使用EDS文件(硬编码方式)
Console.WriteLine("\n场景2: 不使用EDS文件");
master.AddNode(2, "Simple_IO");
// 手动读写已知对象
master.SdoWriteAndWait(2, 0x6200, 0x01, 0x000000FF);
var response = master.SdoReadAndWait(2, 0x6000, 0x01);
if (response != null)
{
uint value = BitConverter.ToUInt32(response, 4);
Console.WriteLine($" 读取值: 0x{value:X8}");
}
// 场景3: 混合使用
Console.WriteLine("\n场景3: 混合使用(部分节点用EDS,部分不用)");
master.AddNode(3, "Device_A", servoEds); // 有EDS
master.AddNode(4, "Device_B"); // 无EDS
Console.WriteLine("\n完成!");
}
}
///
/// 简单的CANopen主站测试
///
static void SimpleCanOpenMasterTest()
{
Console.WriteLine("=== 简单CANopen主站测试 ===\n");
using (CanOpenMaster master = new CanOpenMaster(4, 0, 0))
{
// 注册基本事件
master.OnHeartbeatReceived += (nodeId, status) =>
{
Console.WriteLine($"[HB] 节点{nodeId}: 0x{status:X2}");
};
master.OnTpdoReceived += (nodeId, data) =>
{
string dataStr = BitConverter.ToString(data).Replace("-", " ");
Console.WriteLine($"[TPDO] 节点{nodeId}: [{dataStr}]");
};
// 初始化
if (!master.Initialize(CanBaudRate.BaudRate_500K))
{
Console.WriteLine("初始化失败");
return;
}
// 添加一个节点
master.AddNode(1);
Console.WriteLine("等待2秒接收心跳...");
Thread.Sleep(2000);
// 尝试读取设备类型
Console.WriteLine("\n读取设备类型...");
uint deviceType = master.ReadDeviceType(1);
Console.WriteLine($"设备类型: 0x{deviceType:X8}");
// 启动节点
Console.WriteLine("\n启动节点...");
master.NmtStartNode(1);
Thread.Sleep(500);
// 发送几次SYNC
Console.WriteLine("\n发送SYNC...");
for (int i = 0; i < 5; i++)
{
master.SendSync((byte)(i + 1));
Thread.Sleep(100);
}
Console.WriteLine("\n测试完成");
}
}
///
/// TPDO接收事件处理
///
private static void Master_OnTpdoReceived(byte nodeId, byte[] data)
{
string dataStr = BitConverter.ToString(data).Replace("-", " ");
Console.WriteLine($"[TPDO] 节点{nodeId}: 数据=[{dataStr}]");
}
///
/// 心跳接收事件处理
///
private static void Master_OnHeartbeatReceived(byte nodeId, byte status)
{
string statusStr = GetNodeStatusString(status);
Console.WriteLine($"[Heartbeat] 节点{nodeId}: 状态={statusStr} (0x{status:X2})");
}
///
/// 紧急消息事件处理
///
private static void Master_OnEmergencyReceived(byte nodeId, ushort errorCode)
{
Console.WriteLine($"[EMERGENCY] 节点{nodeId}: 错误代码=0x{errorCode:X4}");
}
///
/// 日志消息事件处理
///
private static void Master_OnLogMessage(string message)
{
// 可以选择性地输出日志,避免过多输出
// Console.WriteLine(message);
}
///
/// 扫描所有节点的设备信息
///
static void ScanAllNodes(CanOpenMaster master)
{
Console.WriteLine("=== 扫描节点设备信息 ===");
foreach (var nodeId in master.NodeIds)
{
Console.WriteLine($"\n--- 节点 {nodeId} ---");
try
{
// 读取设备类型
uint deviceType = master.ReadDeviceType(nodeId);
Console.WriteLine($" 设备类型: 0x{deviceType:X8}");
// 读取厂商ID
uint vendorId = master.ReadVendorId(nodeId);
Console.WriteLine($" 厂商ID: 0x{vendorId:X8}");
// 读取产品代码
uint productCode = master.ReadProductCode(nodeId);
Console.WriteLine($" 产品代码: 0x{productCode:X8}");
// 读取序列号
uint serialNumber = master.ReadSerialNumber(nodeId);
Console.WriteLine($" 序列号: 0x{serialNumber:X8}");
// 更新节点信息
var node = master.GetNode(nodeId);
if (node != null)
{
Console.WriteLine($" 状态: {node.GetStateString()}");
Console.WriteLine($" 在线: {(node.IsOnline() ? "是" : "否")}");
}
}
catch (Exception ex)
{
Console.WriteLine($" 读取失败: {ex.Message}");
}
Thread.Sleep(50); // 避免总线拥塞
}
}
///
/// 读取节点参数
///
static void ReadNodeParameters(CanOpenMaster master, byte nodeId)
{
var node = master.GetNode(nodeId);
if (node == null) return;
// 示例:读取对象字典中的某个参数
// 这里读取0x6000:01 (假设是数字输入状态)
var response = master.SdoReadAndWait(nodeId, 0x6000, 0x01, 500);
if (response != null && response.Length >= 5)
{
uint value = BitConverter.ToUInt32(response, 4);
Console.WriteLine($"[SDO Read] 节点{nodeId}, 索引0x6000:01 = 0x{value:X8}");
}
}
///
/// 写入控制命令(SDO方式)
///
static void WriteControlCommand(CanOpenMaster master, byte nodeId)
{
var node = master.GetNode(nodeId);
if (node == null) return;
// 示例:写入对象字典中的某个参数
// 这里写入0x6200:01 (假设是数字输出控制)
uint controlValue = 0x00000001; // 设置第1位
bool success = master.SdoWriteAndWait(nodeId, 0x6200, 0x01, controlValue, 500);
if (success)
{
Console.WriteLine($"[SDO Write] 节点{nodeId}, 索引0x6200:01 = 0x{controlValue:X8} - 成功");
}
else
{
Console.WriteLine($"[SDO Write] 节点{nodeId}, 索引0x6200:01 = 0x{controlValue:X8} - 失败");
}
}
///
/// 通过RPDO发送控制数据(PDO方式 - 高速)
///
static int rpdoCount = 0;
static void SendRpdoControl(CanOpenMaster master, byte nodeId)
{
var node = master.GetNode(nodeId);
if (node == null) return;
// 准备RPDO数据(根据映射配置)
// 假设RPDO1映射: 0x6200:01 (DO1, 8位), 0x6200:02 (DO2, 8位)
byte[] rpdoData = new byte[2];
rpdoData[0] = 0xFF; // DO1全部置ON
rpdoData[1] = 0x00; // DO2全部置OFF
// 发送RPDO
bool success = master.SendRpdo(nodeId, 1, rpdoData);
if (success)
{
// 每50次打印一次,避免刷屏
rpdoCount++;
if (rpdoCount % 50 == 0)
{
Console.WriteLine($"[RPDO Write] 节点{nodeId}, RPDO1: DO1=0x{rpdoData[0]:X2}, DO2=0x{rpdoData[1]:X2}");
}
}
}
///
/// 演示PDO映射配置
///
static void PdoMappingExample(CanOpenMaster master, byte nodeId)
{
Console.WriteLine($"\n=== 配置节点{nodeId}的PDO映射 ===");
// 配置RPDO1映射
var rpdo1Mapping = new List
{
new MappedObject { Index = 0x6200, SubIndex = 0x01, BitLength = 8 }, // DO1
new MappedObject { Index = 0x6200, SubIndex = 0x02, BitLength = 8 } // DO2
};
bool success = master.ConfigureRpdoMapping(nodeId, 1, rpdo1Mapping);
Console.WriteLine($"RPDO1映射配置: {(success ? "成功" : "失败")}");
// 配置TPDO1映射
var tpdo1Mapping = new List
{
new MappedObject { Index = 0x6400, SubIndex = 0x01, BitLength = 16 }, // AI1
new MappedObject { Index = 0x6400, SubIndex = 0x02, BitLength = 16 } // AI2
};
success = master.ConfigureTpdoMapping(nodeId, 1, tpdo1Mapping);
Console.WriteLine($"TPDO1映射配置: {(success ? "成功" : "失败")}");
}
///
/// 打印节点状态
///
static void PrintNodeStatus(CanOpenMaster master)
{
Console.WriteLine("\n--- 节点状态 ---");
foreach (var nodeId in master.NodeIds)
{
var node = master.GetNode(nodeId);
if (node != null)
{
Console.WriteLine(node.ToString());
}
}
Console.WriteLine();
}
///
/// 获取节点状态字符串
///
static string GetNodeStatusString(byte status)
{
switch (status & 0x7F)
{
case 0x00: return "启动中";
case 0x04: return "停止";
case 0x05: return "运行";
case 0x7F: return "预操作";
default: return "未知";
}
}
static void ConnectCan()
{
//string SendId = "0x0000000f";
//开启设备
if (CanLibraryClass.VCI_OpenDevice(m_devtype, m_devind, 0) == 0)
{
Console.WriteLine("打开设备失败,请检查设备类型和设备索引号是否正确");
return;
}
//初始化CAN
VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();
config.AccCode = Convert.ToUInt32("0x00000000", 16);
config.AccMask = Convert.ToUInt32("0xFFFFFFFF", 16);
config.Timing0 = Convert.ToByte("0x00", 16);
config.Timing1 = Convert.ToByte("0x14", 16);
config.Filter = (Byte)1;
config.Mode = (Byte)0;
if (CanLibraryClass.VCI_InitCAN(m_devtype, m_devind, m_canind, ref config) == 0)
{
Console.WriteLine("初始化Can失败");
return;
}
if (CanLibraryClass.VCI_StartCAN(m_devtype, m_devind, m_canind) == 0)
{
Console.WriteLine("开启Can失败");
return;
}
}
unsafe static void SendTest()
{
int DataLen = 1;
int SendCount = 0;
int sendnum = 0;
int InSendCount = 0;
TimeSpan WhileSleepTime = TimeSpan.FromTicks(10000 * 4);
Stopwatch SW = new Stopwatch();
Stopwatch RunTime = new Stopwatch();
Console.WriteLine("请输入循环次数");
InSendCount = Convert.ToInt32(Console.ReadLine());
RunTime.Start();
while (SendCount < InSendCount)
{
SW.Restart();
VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ();
sendobj.RemoteFlag = (byte)(0);
sendobj.ExternFlag = (byte)(0);
sendobj.ID = Convert.ToUInt32(Convert.ToString(2, 16), 16);
sendobj.DataLen = Convert.ToByte(DataLen);
for (int i = 1; i < DataLen + 1; i++)
{
sendobj.Data[i - 1] = BitConverter.GetBytes(sendnum % 256)[0];
sendnum++;
}
if (CanLibraryClass.VCI_Transmit(m_devtype, m_devind, m_canind, ref sendobj, 1) == 0)
{
Console.WriteLine("发送失败");
continue;
}
SendCount++;
Console.WriteLine("运行时常:{0},帧ID:{1},帧发送耗时:{2}\n" +
"Data0:{3},Data0:{4},Data0:{5},Data0:{6},\n" +
"Data0:{7},Data0:{8},Data0:{9},Data0:{10},",
RunTime.Elapsed, SendCount, SW.Elapsed,
sendobj.Data[0], sendobj.Data[1], sendobj.Data[2], sendobj.Data[3],
sendobj.Data[4], sendobj.Data[5], sendobj.Data[6], sendobj.Data[7]);
while (SW.Elapsed <= WhileSleepTime)
{
}
if (SendCount == InSendCount)
{
RunTime.Stop();
Console.WriteLine("总耗时:{0}", RunTime.Elapsed);
Console.WriteLine("输入新的循环数(输入0结束):");
int newnum = Convert.ToInt32(Console.ReadLine());
if (newnum != 0)
{
SendCount = 0;
InSendCount = newnum;
RunTime.Restart();
}
}
}
CanLibraryClass.VCI_ResetCAN(m_devtype, m_devind, m_canind);
Console.WriteLine("流程完成");
Console.ReadKey();
}
unsafe static void GetTest()
{
UInt32 res = new UInt32();
VCI_CAN_OBJ[] m_recobj = new VCI_CAN_OBJ[1000];
Console.WriteLine("请输入运行时长(单位:分钟)");
int runtimeLength = Convert.ToInt32(Console.ReadLine());
DateTime StartTime = DateTime.Now;
int getCount = 0;
Task SetTask = new Task(() =>
{
while ((DateTime.Now - StartTime).TotalMilliseconds < runtimeLength * 60 * 1000)
{
res = CanLibraryClass.VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0], 1000, 100);
getCount++;
if (res == 0xFFFFFFFF) res = 0;
if (res != 0)
{
for (UInt32 i = 0; i < res; i++)
{
string str = "";
str = "接收到数据: ";
str += " 帧ID:0x" + System.Convert.ToString(m_recobj[i].ID, 16);
str += " 帧格式:";
if (m_recobj[i].RemoteFlag == 0)
str += "数据帧 ";
else
str += "远程帧 ";
if (m_recobj[i].ExternFlag == 0)
str += "标准帧 ";
else
str += "扩展帧 ";
if (m_recobj[i].RemoteFlag == 0)
{
fixed (VCI_CAN_OBJ* m_recobj1 = &m_recobj[i])
{
str += "数据:";
for (byte k = 0; k < 8; k++)
{
str += " " + m_recobj1->Data[k].ToString("X2");
}
}
}
Console.WriteLine(str);
}
}
}
Console.WriteLine("运行结束,运行次数{0}", getCount);
CanLibraryClass.VCI_ResetCAN(m_devtype, m_devind, m_canind);
});
SetTask.Start();
Console.ReadKey();
}
unsafe static void MessageTest()
{
UInt32 res = new UInt32();
VCI_CAN_OBJ[] m_recobj = new VCI_CAN_OBJ[1000];
Console.WriteLine("请输入运行时长(单位:分钟)");
int runtimeLength = Convert.ToInt32(Console.ReadLine());
DateTime StartTime = DateTime.Now;
int getCount = 0;
int DataLen = 8;
int SendCount = 0;
//Stopwatch SW = new Stopwatch();
Stopwatch InterValSW = new Stopwatch();
TimeSpan WhileSleepTime = TimeSpan.FromTicks(10000 * 1);
TimeSpan MaxTime = TimeSpan.MinValue;
TimeSpan MinTime = TimeSpan.MaxValue;
int num04 = 0;
int num48 = 0;
int num8p = 0;
Task SetTask = new Task(() =>
{
int previousWriteDone = 0;
while ((DateTime.Now - StartTime).TotalMilliseconds < runtimeLength * 60 * 1000)
{
//SW.Restart();
InterValSW.Restart();
res = CanLibraryClass.VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0], 1000, 100);
if (res == 0xFFFFFFFF) res = 0;
//if (res == 0) Console.WriteLine("res=0");
if (res != 0)
{
for (UInt32 i = 0; i < res; i++)
{
string str = "";
if (m_recobj[i].RemoteFlag == 0)
{
getCount++;
int writeDone = -1;
fixed (VCI_CAN_OBJ* m_recobj1 = &m_recobj[i])
{
writeDone = m_recobj1->Data[6] & 0x01;
//if(true)
if (writeDone != previousWriteDone)
{
str = DateTime.Now.ToString("HH mm ss ffffff:");
str += "运行次数:" + getCount;
str += "接收到数据: ";
str += " 帧ID:0x" + System.Convert.ToString(m_recobj[i].ID, 16);
str += " 帧格式:";
if (m_recobj[i].RemoteFlag == 0)
str += "数据帧 ";
else
str += "远程帧 ";
if (m_recobj[i].ExternFlag == 0)
str += "标准帧 ";
else
str += "扩展帧 ";
str += "数据:";
for (byte k = 0; k < 8; k++)
{
str += " " + m_recobj1->Data[k].ToString("X2");
}
}
}
if ((writeDone == 1 && previousWriteDone == 0) || (writeDone == 0 && previousWriteDone == 1))
{
VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ();
sendobj.RemoteFlag = (byte)(0);
sendobj.ExternFlag = (byte)(0);
sendobj.ID = Convert.ToUInt32(Convert.ToString(2, 16), 16);
sendobj.DataLen = Convert.ToByte(DataLen);
byte SendMessage0 = new byte();
SendMessage0 |= (byte)(1 << SendCount % 8);
//SendMessage0 |= (byte)(1 << 0);
sendobj.Data[0] = SendMessage0;
byte SendMessage1 = new byte();
SendMessage1 |= (byte)(1 << SendCount % 8);
//SendMessage1 |= (byte)(1 << 0);
sendobj.Data[1] = SendMessage1;
byte SendMessage6 = new byte();
SendMessage6 = (byte)(1 << 0);
sendobj.Data[6] = SendMessage6;
byte SendMessage7 = new byte();
if (SendCount % 10 == 0)
SendMessage7 |= (byte)(1 << 0);
if (SendCount % 11 == 0)
SendMessage7 |= (byte)(1 << 1);
sendobj.Data[7] = SendMessage7;
str += "发送数据:";
str += string.Format("byte0:{0},byte1:{1},byte6:{2},byte7:{3}",
SendMessage0.ToString("000"), SendMessage1.ToString("000"),
SendMessage6.ToString("000"), SendMessage7.ToString("000"));
if (CanLibraryClass.VCI_Transmit(m_devtype, m_devind, m_canind, ref sendobj, 1) == 0)
{
Console.WriteLine("发送失败");
continue;
}
InterValSW.Stop();
if (SendCount != 0)
{
MaxTime = InterValSW.Elapsed > MaxTime ? InterValSW.Elapsed : MaxTime;
MinTime = InterValSW.Elapsed < MinTime ? InterValSW.Elapsed : MinTime;
if (InterValSW.Elapsed <= TimeSpan.FromMilliseconds(4))
{
num04++;
}
else if (InterValSW.Elapsed <= TimeSpan.FromMilliseconds(8))
{
num48++;
}
else
{
num8p++;
}
}
else
{
StartTime = DateTime.Now;
}
SendCount++;
}
previousWriteDone = writeDone;
}
if (!string.IsNullOrEmpty(str))
Console.WriteLine(str);
}
}
//while (SW.Elapsed <= WhileSleepTime)
//{
//}
}
Console.WriteLine("运行结束,运行次数{0},发送次数{1},最小耗时{2},最大耗时{3}",
getCount, SendCount, MinTime.TotalMilliseconds, MaxTime.TotalMilliseconds);
Console.WriteLine("运行耗时统计,0-4:{0},4-8:{1},8+:{2}", num04, num48, num8p);
CanLibraryClass.VCI_ResetCAN(m_devtype, m_devind, m_canind);
});
SetTask.Start();
Console.ReadKey();
}
}
}