using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CCDCount.DLL.CanBus
{
///
/// CANopen对象字典管理器
/// 存储和管理CANopen从站的所有对象
///
public class ObjectDictionary
{
private byte m_nodeId;
private Dictionary> m_objects;
public ObjectDictionary(byte nodeId)
{
m_nodeId = nodeId;
m_objects = new Dictionary>();
InitializeStandardObjects();
}
///
/// 初始化标准CANopen对象
///
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); // 模拟输出值
}
}
///
/// 读取对象字典值
///
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];
}
///
/// 写入对象字典值
///
public bool Write(ushort index, byte subIndex, object value)
{
if (!m_objects.ContainsKey(index))
{
m_objects[index] = new Dictionary();
}
m_objects[index][subIndex] = value;
return true;
}
///
/// 获取所有对象
///
public Dictionary> GetAllObjects()
{
return m_objects;
}
///
/// 检查对象是否存在
///
public bool Exists(ushort index, byte subIndex)
{
return m_objects.ContainsKey(index) && m_objects[index].ContainsKey(subIndex);
}
}
}