using CCDCount.DLL.CanBus; using System; namespace CanOpenUsageExample { /// /// CanOpenManager 使用示例 /// 演示如何直接使用创芯科技CAN卡进行CANopen通信 /// public class CanOpenExample { public void Example1_BasicUsage() { // 1. 创建CANopen管理器 using (var canOpen = new CanOpenManager(deviceType: 4, deviceIndex: 0, canIndex: 0)) { // 2. 初始化(默认500kbps) if (!canOpen.Initialize(CanBaudRate.BaudRate_1M)) { Console.WriteLine("初始化失败!"); return; } Console.WriteLine("CANopen管理器初始化成功!"); // 3. NMT - 启动节点1 canOpen.NmtStartNode(1); // 4. SDO - 读取设备类型(索引0x1000) byte[] response = canOpen.SdoReadAndWait(1, 0x1000, 0x00, 1000); if (response != null) { Console.WriteLine($"设备类型读取成功"); } // 5. SDO - 写入参数 bool success = canOpen.SdoWriteAndWait(1, 0x6040, 0x00, 0x0006, 1000); Console.WriteLine($"SDO写入: {(success ? "成功" : "失败")}"); // 6. PDO - 发送同步帧 canOpen.SendSync(); // 7. PDO - 配置传输类型 canOpen.ConfigureTpdoTransmissionType(1, 1, 254); // 事件驱动 // 8. 接收数据 var frames = canOpen.ReceiveCanFrames(100); foreach (var frame in frames) { Console.WriteLine($"收到帧: {frame}"); } } // using语句会自动调用Dispose()关闭设备 } public void Example2_NmtControl() { using (var canOpen = new CanOpenManager()) { canOpen.Initialize(); // NMT状态机控制 byte nodeId = 1; // 重置节点 canOpen.NmtResetNode(nodeId); System.Threading.Thread.Sleep(100); // 进入预操作状态 canOpen.NmtEnterPreOperational(nodeId); System.Threading.Thread.Sleep(100); // 启动节点 canOpen.NmtStartNode(nodeId); System.Threading.Thread.Sleep(100); // 停止节点 canOpen.NmtStopNode(nodeId); } } public void Example3_SdoCommunication() { using (var canOpen = new CanOpenManager()) { canOpen.Initialize(); byte nodeId = 1; // 方式1: 异步发送,稍后接收 canOpen.SdoReadQuick(nodeId, 0x1000, 0x00); System.Threading.Thread.Sleep(50); var response = canOpen.ReceiveSdoResponse(nodeId, 1000); // 方式2: 同步阻塞方式(推荐) var data = canOpen.SdoReadAndWait(nodeId, 0x1018, 0x01, 1000); if (data != null) { // 解析响应数据 uint vendorId = BitConverter.ToUInt32(data, 4); Console.WriteLine($"厂商ID: 0x{vendorId:X8}"); } // 写入4字节数据 canOpen.SdoWriteAndWait(nodeId, 0x6040, 0x00, 0x0006, 1000); } } public void Example4_PdoCommunication() { using (var canOpen = new CanOpenManager()) { canOpen.Initialize(); byte nodeId = 1; // 周期性发送SYNC for (int i = 0; i < 100; i++) { canOpen.SendSync((byte)(i % 256)); // 带计数器 // 接收TPDO1 var tpdo1Data = canOpen.ReceiveRpdo(nodeId, 1, 50); if (tpdo1Data != null) { Console.WriteLine($"收到TPDO1数据长度: {tpdo1Data.Length}"); } System.Threading.Thread.Sleep(10); // 10ms周期 } // 发送RPDO1数据到从站 byte[] rpdoData = new byte[] { 0x01, 0x02, 0x03, 0x04 }; canOpen.SendTpdo(nodeId, 1, rpdoData); } } public void Example5_EmergencyAndHeartbeat() { using (var canOpen = new CanOpenManager()) { canOpen.Initialize(); // 监听紧急消息和心跳 while (true) { var frames = canOpen.ReceiveCanFrames(100); foreach (var frame in frames) { // 检测紧急消息 (COB-ID: 0x080 + nodeId) if (frame.CobId >= 0x081 && frame.CobId <= 0x0FF) { byte nodeId = (byte)(frame.CobId - 0x080); ushort errorCode = canOpen.ParseEmergencyMessage(frame.Data); Console.WriteLine($"节点{nodeId}紧急错误: 0x{errorCode:X4}"); } // 检测心跳 (COB-ID: 0x700 + nodeId) if (frame.CobId >= 0x701 && frame.CobId <= 0x77F) { byte nodeId = (byte)(frame.CobId - 0x700); byte status = canOpen.ParseHeartbeat(nodeId, frame.Data); } } } } } public void Example6_MultiNodeNetwork() { using (var canOpen = new CanOpenManager()) { canOpen.Initialize(); // 启动多个节点 byte[] nodeIds = { 1, 2, 3, 4, 5 }; foreach (byte nodeId in nodeIds) { canOpen.NmtStartNode(nodeId); System.Threading.Thread.Sleep(50); } // 轮询所有节点的SDO foreach (byte nodeId in nodeIds) { var data = canOpen.SdoReadAndWait(nodeId, 0x1000, 0x00, 500); if (data != null) { Console.WriteLine($"节点{nodeId}在线"); } else { Console.WriteLine($"节点{nodeId}无响应"); } } } } } }