CanOpenUsageExample.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using CCDCount.DLL.CanBus;
  2. using System;
  3. namespace CanOpenUsageExample
  4. {
  5. /// <summary>
  6. /// CanOpenManager 使用示例
  7. /// 演示如何直接使用创芯科技CAN卡进行CANopen通信
  8. /// </summary>
  9. public class CanOpenExample
  10. {
  11. public void Example1_BasicUsage()
  12. {
  13. // 1. 创建CANopen管理器
  14. using (var canOpen = new CanOpenManager(deviceType: 4, deviceIndex: 0, canIndex: 0))
  15. {
  16. // 2. 初始化(默认500kbps)
  17. if (!canOpen.Initialize(CanBaudRate.BaudRate_1M))
  18. {
  19. Console.WriteLine("初始化失败!");
  20. return;
  21. }
  22. Console.WriteLine("CANopen管理器初始化成功!");
  23. // 3. NMT - 启动节点1
  24. canOpen.NmtStartNode(1);
  25. // 4. SDO - 读取设备类型(索引0x1000)
  26. byte[] response = canOpen.SdoReadAndWait(1, 0x1000, 0x00, 1000);
  27. if (response != null)
  28. {
  29. Console.WriteLine($"设备类型读取成功");
  30. }
  31. // 5. SDO - 写入参数
  32. bool success = canOpen.SdoWriteAndWait(1, 0x6040, 0x00, 0x0006, 1000);
  33. Console.WriteLine($"SDO写入: {(success ? "成功" : "失败")}");
  34. // 6. PDO - 发送同步帧
  35. canOpen.SendSync();
  36. // 7. PDO - 配置传输类型
  37. canOpen.ConfigureTpdoTransmissionType(1, 1, 254); // 事件驱动
  38. // 8. 接收数据
  39. var frames = canOpen.ReceiveCanFrames(100);
  40. foreach (var frame in frames)
  41. {
  42. Console.WriteLine($"收到帧: {frame}");
  43. }
  44. }
  45. // using语句会自动调用Dispose()关闭设备
  46. }
  47. public void Example2_NmtControl()
  48. {
  49. using (var canOpen = new CanOpenManager())
  50. {
  51. canOpen.Initialize();
  52. // NMT状态机控制
  53. byte nodeId = 1;
  54. // 重置节点
  55. canOpen.NmtResetNode(nodeId);
  56. System.Threading.Thread.Sleep(100);
  57. // 进入预操作状态
  58. canOpen.NmtEnterPreOperational(nodeId);
  59. System.Threading.Thread.Sleep(100);
  60. // 启动节点
  61. canOpen.NmtStartNode(nodeId);
  62. System.Threading.Thread.Sleep(100);
  63. // 停止节点
  64. canOpen.NmtStopNode(nodeId);
  65. }
  66. }
  67. public void Example3_SdoCommunication()
  68. {
  69. using (var canOpen = new CanOpenManager())
  70. {
  71. canOpen.Initialize();
  72. byte nodeId = 1;
  73. // 方式1: 异步发送,稍后接收
  74. canOpen.SdoReadQuick(nodeId, 0x1000, 0x00);
  75. System.Threading.Thread.Sleep(50);
  76. var response = canOpen.ReceiveSdoResponse(nodeId, 1000);
  77. // 方式2: 同步阻塞方式(推荐)
  78. var data = canOpen.SdoReadAndWait(nodeId, 0x1018, 0x01, 1000);
  79. if (data != null)
  80. {
  81. // 解析响应数据
  82. uint vendorId = BitConverter.ToUInt32(data, 4);
  83. Console.WriteLine($"厂商ID: 0x{vendorId:X8}");
  84. }
  85. // 写入4字节数据
  86. canOpen.SdoWriteAndWait(nodeId, 0x6040, 0x00, 0x0006, 1000);
  87. }
  88. }
  89. public void Example4_PdoCommunication()
  90. {
  91. using (var canOpen = new CanOpenManager())
  92. {
  93. canOpen.Initialize();
  94. byte nodeId = 1;
  95. // 周期性发送SYNC
  96. for (int i = 0; i < 100; i++)
  97. {
  98. canOpen.SendSync((byte)(i % 256)); // 带计数器
  99. // 接收TPDO1
  100. var tpdo1Data = canOpen.ReceiveRpdo(nodeId, 1, 50);
  101. if (tpdo1Data != null)
  102. {
  103. Console.WriteLine($"收到TPDO1数据长度: {tpdo1Data.Length}");
  104. }
  105. System.Threading.Thread.Sleep(10); // 10ms周期
  106. }
  107. // 发送RPDO1数据到从站
  108. byte[] rpdoData = new byte[] { 0x01, 0x02, 0x03, 0x04 };
  109. canOpen.SendTpdo(nodeId, 1, rpdoData);
  110. }
  111. }
  112. public void Example5_EmergencyAndHeartbeat()
  113. {
  114. using (var canOpen = new CanOpenManager())
  115. {
  116. canOpen.Initialize();
  117. // 监听紧急消息和心跳
  118. while (true)
  119. {
  120. var frames = canOpen.ReceiveCanFrames(100);
  121. foreach (var frame in frames)
  122. {
  123. // 检测紧急消息 (COB-ID: 0x080 + nodeId)
  124. if (frame.CobId >= 0x081 && frame.CobId <= 0x0FF)
  125. {
  126. byte nodeId = (byte)(frame.CobId - 0x080);
  127. ushort errorCode = canOpen.ParseEmergencyMessage(frame.Data);
  128. Console.WriteLine($"节点{nodeId}紧急错误: 0x{errorCode:X4}");
  129. }
  130. // 检测心跳 (COB-ID: 0x700 + nodeId)
  131. if (frame.CobId >= 0x701 && frame.CobId <= 0x77F)
  132. {
  133. byte nodeId = (byte)(frame.CobId - 0x700);
  134. byte status = canOpen.ParseHeartbeat(nodeId, frame.Data);
  135. }
  136. }
  137. }
  138. }
  139. }
  140. public void Example6_MultiNodeNetwork()
  141. {
  142. using (var canOpen = new CanOpenManager())
  143. {
  144. canOpen.Initialize();
  145. // 启动多个节点
  146. byte[] nodeIds = { 1, 2, 3, 4, 5 };
  147. foreach (byte nodeId in nodeIds)
  148. {
  149. canOpen.NmtStartNode(nodeId);
  150. System.Threading.Thread.Sleep(50);
  151. }
  152. // 轮询所有节点的SDO
  153. foreach (byte nodeId in nodeIds)
  154. {
  155. var data = canOpen.SdoReadAndWait(nodeId, 0x1000, 0x00, 500);
  156. if (data != null)
  157. {
  158. Console.WriteLine($"节点{nodeId}在线");
  159. }
  160. else
  161. {
  162. Console.WriteLine($"节点{nodeId}无响应");
  163. }
  164. }
  165. }
  166. }
  167. }
  168. }