| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace CCDCount.DLL.CanBus
- {
- /// <summary>
- /// CANopen对象字典管理器
- /// 存储和管理CANopen从站的所有对象
- /// </summary>
- public class ObjectDictionary
- {
- private byte m_nodeId;
- private Dictionary<ushort, Dictionary<byte, object>> m_objects;
-
- public ObjectDictionary(byte nodeId)
- {
- m_nodeId = nodeId;
- m_objects = new Dictionary<ushort, Dictionary<byte, object>>();
- InitializeStandardObjects();
- }
-
- /// <summary>
- /// 初始化标准CANopen对象
- /// </summary>
- private void InitializeStandardObjects()
- {
- // ========== 通信参数区域 (0x1000-0x1FFF) ==========
-
- // 0x1000:00 - 设备类型 (必须符合CANopen规范)
- // 格式: [0-15位: 设备轮廓] [16-31位: 附加信息]
- // 0x00000190 = 通用I/O设备 (Generic I/O Device)
- Write(0x1000, 0x00, (uint)0x00000190);
-
- // 0x1001:00 - 错误寄存器
- Write(0x1001, 0x00, (byte)0x00);
-
- // 0x1005:00 - COB-ID SYNC
- Write(0x1005, 0x00, (uint)0x00000080);
-
- // 0x1006:00 - 同步窗口时间
- Write(0x1006, 0x00, (uint)0);
-
- // 0x1007:00 - 同步溢出周期
- Write(0x1007, 0x00, (uint)0);
-
- // 0x1008:00 - 制造商设备名称
- Write(0x1008, 0x00, "CCDCount CANopen Slave Device");
-
- // 0x1009:00 - 制造商硬件版本
- Write(0x1009, 0x00, "1.0.0");
-
- // 0x100A:00 - 制造商软件版本
- Write(0x100A, 0x00, "1.0.0");
-
- // 0x1017:00 - 生产者心跳时间
- Write(0x1017, 0x00, (ushort)1000);
-
- // 0x1018:00 - 身份对象(子索引0表示条目数)
- Write(0x1018, 0x00, (byte)4);
- Write(0x1018, 0x01, (uint)0x00000133); // Vendor ID (示例值,实际应使用CiA分配的厂商ID)
- Write(0x1018, 0x02, (uint)0x00000001); // Product Code (产品代码,由厂商定义)
- Write(0x1018, 0x03, (uint)0x00010001); // Revision Number (版本号: Major.Minor)
- Write(0x1018, 0x04, (uint)((uint)m_nodeId)); // Serial Number (序列号)
-
- // ========== RPDO通信参数 (0x1400-0x15FF) ==========
- for (int i = 0; i < 4; i++)
- {
- ushort commIndex = (ushort)(0x1400 + i);
- Write(commIndex, 0x00, (byte)2); // 子条目数量
-
- if (i < 2)
- {
- // 前两个RPDO启用(清除最高位0x80000000)
- Write(commIndex, 0x01, (uint)(0x200 + m_nodeId + i * 0x100)); // COB-ID (启用)
- }
- else
- {
- // 后两个RPDO禁用
- Write(commIndex, 0x01, (uint)(0x200 + m_nodeId + i * 0x100 | 0x80000000)); // COB-ID (禁用)
- }
-
- Write(commIndex, 0x02, (byte)255); // 传输类型
- }
-
- // ========== TPDO通信参数 (0x1800-0x19FF) ==========
- for (int i = 0; i < 4; i++)
- {
- ushort commIndex = (ushort)(0x1800 + i);
- Write(commIndex, 0x00, (byte)6); // 子条目数量
-
- if (i < 2)
- {
- // 前两个TPDO启用(清除最高位0x80000000)
- Write(commIndex, 0x01, (uint)(0x180 + m_nodeId + i * 0x100)); // COB-ID (启用)
- }
- else
- {
- // 后两个TPDO禁用
- Write(commIndex, 0x01, (uint)(0x180 + m_nodeId + i * 0x100 | 0x80000000)); // COB-ID (禁用)
- }
-
- Write(commIndex, 0x02, (byte)255); // 传输类型
- Write(commIndex, 0x03, (ushort)0); // 抑制时间
- Write(commIndex, 0x05, (ushort)0); // 事件定时器
- Write(commIndex, 0x06, (byte)0); // SYNC启动值
- }
-
- // ========== RPDO映射参数 (0x1600-0x17FF) ==========
- // RPDO 1: 映射数字输入状态 (0x6000:01-02)
- Write(0x1600, 0x00, (byte)2); // 映射条目数量
- Write(0x1600, 0x01, (uint)0x60000108); // 0x6000:01, 8位 (DI1)
- Write(0x1600, 0x02, (uint)0x60000208); // 0x6000:02, 8位 (DI2)
-
- // RPDO 2: 映射数字输出控制 (0x6200:01-02)
- Write(0x1601, 0x00, (byte)2); // 映射条目数量
- Write(0x1601, 0x01, (uint)0x62000108); // 0x6200:01, 8位 (DO1)
- Write(0x1601, 0x02, (uint)0x62000208); // 0x6200:02, 8位 (DO2)
-
- // RPDO 3: 未配置
- Write(0x1602, 0x00, (byte)0); // 映射条目数量
-
- // RPDO 4: 未配置
- Write(0x1603, 0x00, (byte)0); // 映射条目数量
-
- // ========== TPDO映射参数 (0x1A00-0x1BFF) ==========
- // TPDO 1: 映射模拟输入值 (0x6400:01-02)
- Write(0x1A00, 0x00, (byte)2); // 映射条目数量
- Write(0x1A00, 0x01, (uint)0x64000110); // 0x6400:01, 16位 (AI1)
- Write(0x1A00, 0x02, (uint)0x64000210); // 0x6400:02, 16位 (AI2)
-
- // TPDO 2: 映射模拟输出值 (0x6410:01-02)
- Write(0x1A01, 0x00, (byte)2); // 映射条目数量
- Write(0x1A01, 0x01, (uint)0x64100110); // 0x6410:01, 16位 (AO1)
- Write(0x1A01, 0x02, (uint)0x64100210); // 0x6410:02, 16位 (AO2)
-
- // TPDO 3: 未配置
- Write(0x1A02, 0x00, (byte)0); // 映射条目数量
-
- // TPDO 4: 未配置
- Write(0x1A03, 0x00, (byte)0); // 映射条目数量
-
- // ========== 制造商特定区域 (0x2000-0x5FFF) ==========
- // 这里可以添加自定义对象
- // 示例:数字输入
- Write(0x6000, 0x00, (byte)8); // 子条目数量
- for (byte i = 1; i <= 8; i++)
- {
- Write(0x6000, i, (byte)0); // 数字输入状态
- }
-
- // 示例:数字输出
- Write(0x6200, 0x00, (byte)8);
- for (byte i = 1; i <= 8; i++)
- {
- Write(0x6200, i, (byte)0); // 数字输出控制
- }
-
- // 示例:模拟输入
- Write(0x6400, 0x00, (byte)4);
- for (byte i = 1; i <= 4; i++)
- {
- Write(0x6400, i, (ushort)0); // 模拟输入值
- }
-
- // 示例:模拟输出
- Write(0x6410, 0x00, (byte)2);
- for (byte i = 1; i <= 2; i++)
- {
- Write(0x6410, i, (ushort)0); // 模拟输出值
- }
- }
-
- /// <summary>
- /// 读取对象字典值
- /// </summary>
- public object Read(ushort index, byte subIndex)
- {
- if (!m_objects.ContainsKey(index))
- return null;
-
- if (!m_objects[index].ContainsKey(subIndex))
- return null;
-
- return m_objects[index][subIndex];
- }
-
- /// <summary>
- /// 写入对象字典值
- /// </summary>
- public bool Write(ushort index, byte subIndex, object value)
- {
- if (!m_objects.ContainsKey(index))
- {
- m_objects[index] = new Dictionary<byte, object>();
- }
-
- m_objects[index][subIndex] = value;
- return true;
- }
-
- /// <summary>
- /// 获取所有对象
- /// </summary>
- public Dictionary<ushort, Dictionary<byte, object>> GetAllObjects()
- {
- return m_objects;
- }
-
- /// <summary>
- /// 检查对象是否存在
- /// </summary>
- public bool Exists(ushort index, byte subIndex)
- {
- return m_objects.ContainsKey(index) && m_objects[index].ContainsKey(subIndex);
- }
- }
- }
|