ObjectDictionary.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace CCDCount.DLL.CanBus
  6. {
  7. /// <summary>
  8. /// CANopen对象字典管理器
  9. /// 存储和管理CANopen从站的所有对象
  10. /// </summary>
  11. public class ObjectDictionary
  12. {
  13. private byte m_nodeId;
  14. private Dictionary<ushort, Dictionary<byte, object>> m_objects;
  15. public ObjectDictionary(byte nodeId)
  16. {
  17. m_nodeId = nodeId;
  18. m_objects = new Dictionary<ushort, Dictionary<byte, object>>();
  19. InitializeStandardObjects();
  20. }
  21. /// <summary>
  22. /// 初始化标准CANopen对象
  23. /// </summary>
  24. private void InitializeStandardObjects()
  25. {
  26. // ========== 通信参数区域 (0x1000-0x1FFF) ==========
  27. // 0x1000:00 - 设备类型 (必须符合CANopen规范)
  28. // 格式: [0-15位: 设备轮廓] [16-31位: 附加信息]
  29. // 0x00000190 = 通用I/O设备 (Generic I/O Device)
  30. Write(0x1000, 0x00, (uint)0x00000190);
  31. // 0x1001:00 - 错误寄存器
  32. Write(0x1001, 0x00, (byte)0x00);
  33. // 0x1005:00 - COB-ID SYNC
  34. Write(0x1005, 0x00, (uint)0x00000080);
  35. // 0x1006:00 - 同步窗口时间
  36. Write(0x1006, 0x00, (uint)0);
  37. // 0x1007:00 - 同步溢出周期
  38. Write(0x1007, 0x00, (uint)0);
  39. // 0x1008:00 - 制造商设备名称
  40. Write(0x1008, 0x00, "CCDCount CANopen Slave Device");
  41. // 0x1009:00 - 制造商硬件版本
  42. Write(0x1009, 0x00, "1.0.0");
  43. // 0x100A:00 - 制造商软件版本
  44. Write(0x100A, 0x00, "1.0.0");
  45. // 0x1017:00 - 生产者心跳时间
  46. Write(0x1017, 0x00, (ushort)1000);
  47. // 0x1018:00 - 身份对象(子索引0表示条目数)
  48. Write(0x1018, 0x00, (byte)4);
  49. Write(0x1018, 0x01, (uint)0x00000133); // Vendor ID (示例值,实际应使用CiA分配的厂商ID)
  50. Write(0x1018, 0x02, (uint)0x00000001); // Product Code (产品代码,由厂商定义)
  51. Write(0x1018, 0x03, (uint)0x00010001); // Revision Number (版本号: Major.Minor)
  52. Write(0x1018, 0x04, (uint)((uint)m_nodeId)); // Serial Number (序列号)
  53. // ========== RPDO通信参数 (0x1400-0x15FF) ==========
  54. for (int i = 0; i < 4; i++)
  55. {
  56. ushort commIndex = (ushort)(0x1400 + i);
  57. Write(commIndex, 0x00, (byte)2); // 子条目数量
  58. if (i < 2)
  59. {
  60. // 前两个RPDO启用(清除最高位0x80000000)
  61. Write(commIndex, 0x01, (uint)(0x200 + m_nodeId + i * 0x100)); // COB-ID (启用)
  62. }
  63. else
  64. {
  65. // 后两个RPDO禁用
  66. Write(commIndex, 0x01, (uint)(0x200 + m_nodeId + i * 0x100 | 0x80000000)); // COB-ID (禁用)
  67. }
  68. Write(commIndex, 0x02, (byte)255); // 传输类型
  69. }
  70. // ========== TPDO通信参数 (0x1800-0x19FF) ==========
  71. for (int i = 0; i < 4; i++)
  72. {
  73. ushort commIndex = (ushort)(0x1800 + i);
  74. Write(commIndex, 0x00, (byte)6); // 子条目数量
  75. if (i < 2)
  76. {
  77. // 前两个TPDO启用(清除最高位0x80000000)
  78. Write(commIndex, 0x01, (uint)(0x180 + m_nodeId + i * 0x100)); // COB-ID (启用)
  79. }
  80. else
  81. {
  82. // 后两个TPDO禁用
  83. Write(commIndex, 0x01, (uint)(0x180 + m_nodeId + i * 0x100 | 0x80000000)); // COB-ID (禁用)
  84. }
  85. Write(commIndex, 0x02, (byte)255); // 传输类型
  86. Write(commIndex, 0x03, (ushort)0); // 抑制时间
  87. Write(commIndex, 0x05, (ushort)0); // 事件定时器
  88. Write(commIndex, 0x06, (byte)0); // SYNC启动值
  89. }
  90. // ========== RPDO映射参数 (0x1600-0x17FF) ==========
  91. // RPDO 1: 映射数字输入状态 (0x6000:01-02)
  92. Write(0x1600, 0x00, (byte)2); // 映射条目数量
  93. Write(0x1600, 0x01, (uint)0x60000108); // 0x6000:01, 8位 (DI1)
  94. Write(0x1600, 0x02, (uint)0x60000208); // 0x6000:02, 8位 (DI2)
  95. // RPDO 2: 映射数字输出控制 (0x6200:01-02)
  96. Write(0x1601, 0x00, (byte)2); // 映射条目数量
  97. Write(0x1601, 0x01, (uint)0x62000108); // 0x6200:01, 8位 (DO1)
  98. Write(0x1601, 0x02, (uint)0x62000208); // 0x6200:02, 8位 (DO2)
  99. // RPDO 3: 未配置
  100. Write(0x1602, 0x00, (byte)0); // 映射条目数量
  101. // RPDO 4: 未配置
  102. Write(0x1603, 0x00, (byte)0); // 映射条目数量
  103. // ========== TPDO映射参数 (0x1A00-0x1BFF) ==========
  104. // TPDO 1: 映射模拟输入值 (0x6400:01-02)
  105. Write(0x1A00, 0x00, (byte)2); // 映射条目数量
  106. Write(0x1A00, 0x01, (uint)0x64000110); // 0x6400:01, 16位 (AI1)
  107. Write(0x1A00, 0x02, (uint)0x64000210); // 0x6400:02, 16位 (AI2)
  108. // TPDO 2: 映射模拟输出值 (0x6410:01-02)
  109. Write(0x1A01, 0x00, (byte)2); // 映射条目数量
  110. Write(0x1A01, 0x01, (uint)0x64100110); // 0x6410:01, 16位 (AO1)
  111. Write(0x1A01, 0x02, (uint)0x64100210); // 0x6410:02, 16位 (AO2)
  112. // TPDO 3: 未配置
  113. Write(0x1A02, 0x00, (byte)0); // 映射条目数量
  114. // TPDO 4: 未配置
  115. Write(0x1A03, 0x00, (byte)0); // 映射条目数量
  116. // ========== 制造商特定区域 (0x2000-0x5FFF) ==========
  117. // 这里可以添加自定义对象
  118. // 示例:数字输入
  119. Write(0x6000, 0x00, (byte)8); // 子条目数量
  120. for (byte i = 1; i <= 8; i++)
  121. {
  122. Write(0x6000, i, (byte)0); // 数字输入状态
  123. }
  124. // 示例:数字输出
  125. Write(0x6200, 0x00, (byte)8);
  126. for (byte i = 1; i <= 8; i++)
  127. {
  128. Write(0x6200, i, (byte)0); // 数字输出控制
  129. }
  130. // 示例:模拟输入
  131. Write(0x6400, 0x00, (byte)4);
  132. for (byte i = 1; i <= 4; i++)
  133. {
  134. Write(0x6400, i, (ushort)0); // 模拟输入值
  135. }
  136. // 示例:模拟输出
  137. Write(0x6410, 0x00, (byte)2);
  138. for (byte i = 1; i <= 2; i++)
  139. {
  140. Write(0x6410, i, (ushort)0); // 模拟输出值
  141. }
  142. }
  143. /// <summary>
  144. /// 读取对象字典值
  145. /// </summary>
  146. public object Read(ushort index, byte subIndex)
  147. {
  148. if (!m_objects.ContainsKey(index))
  149. return null;
  150. if (!m_objects[index].ContainsKey(subIndex))
  151. return null;
  152. return m_objects[index][subIndex];
  153. }
  154. /// <summary>
  155. /// 写入对象字典值
  156. /// </summary>
  157. public bool Write(ushort index, byte subIndex, object value)
  158. {
  159. if (!m_objects.ContainsKey(index))
  160. {
  161. m_objects[index] = new Dictionary<byte, object>();
  162. }
  163. m_objects[index][subIndex] = value;
  164. return true;
  165. }
  166. /// <summary>
  167. /// 获取所有对象
  168. /// </summary>
  169. public Dictionary<ushort, Dictionary<byte, object>> GetAllObjects()
  170. {
  171. return m_objects;
  172. }
  173. /// <summary>
  174. /// 检查对象是否存在
  175. /// </summary>
  176. public bool Exists(ushort index, byte subIndex)
  177. {
  178. return m_objects.ContainsKey(index) && m_objects[index].ContainsKey(subIndex);
  179. }
  180. }
  181. }