基于Nameless.eds文件实现的CANopen从站设备,使用创芯科技USBCAN2适配器。
主要特性:
CanOpenSlaveTest/
│
├── 📄 核心代码文件
│ ├── CanLibraryClass.cs # CAN卡驱动接口(P/Invoke)
│ ├── CanOpenManager.cs # CANopen协议管理器(基础层)
│ ├── CanOpenSlaveDevice.cs # ⭐ CANopen从站设备(核心实现)
│ ├── EdsValidator.cs # EDS文件验证器
│ ├── Program.cs # 应用程序入口
│ └── SlaveTestForm.cs # ⭐ Windows Forms测试界面
│
├── 📋 配置文件
│ ├── CanOpenSlaveTest.csproj # C#项目文件
│ ├── CanOpenSlaveTest.sln # Visual Studio解决方案
│ └── App.config # 应用配置
│
├── 📚 文档
│ ├── README.md # 完整使用文档
│ ├── QUICKSTART.md # 5分钟快速上手指南
│ └── IMPLEMENTATION_SUMMARY.md # 实现总结和技术细节
│
├── 📁 资源目录
│ ├── bin/Debug/
│ │ ├── controlcan.dll # CAN卡驱动库
│ │ └── Nameless.eds # EDS配置文件
│ ├── Properties/
│ │ └── AssemblyInfo.cs # 程序集信息
│ └── Dll/ # 其他DLL文件
│
└── 📝 其他
└── obj/ # 编译中间文件
# 确保以下文件存在
✓ controlcan.dll 在 bin\Debug\ 目录
✓ USBCAN2设备已连接
✓ CAN总线已正确接线
# 方法1: Visual Studio
打开 CanOpenSlaveTest.sln → F5运行
# 方法2: 命令行
msbuild CanOpenSlaveTest.csproj
cd bin\Debug
CanOpenSlaveTest.exe
1. 点击 [启动从站] 按钮
2. 设置心跳时间 (建议100ms)
3. 点击 [配置心跳]
4. 测试发送TPDO或接收RPDO
| 文档 | 用途 | 适合人群 |
|---|---|---|
| QUICKSTART.md | 5分钟快速上手 | 新手用户 |
| README.md | 完整使用说明和API参考 | 开发者 |
| IMPLEMENTATION_SUMMARY.md | 技术实现细节 | 高级开发者 |
// 创建从站
var slave = new CanOpenSlaveDevice(nodeId: 1);
// 注册事件
slave.OnRpdoReceived += (id, num, data) => { /* 处理RPDO */ };
slave.OnNmtStateChanged += (old, newState) => { /* 状态变化 */ };
// 启动
slave.Start(CanBaudRate.BaudRate_1M);
// 配置心跳
slave.ConfigureHeartbeat(100);
// 发送TPDO
slave.SendTpdo(1);
// 停止
slave.Stop();
slave.Dispose();
CanOpenSlaveDevice
├── NMT管理
│ ├── 启动/停止节点
│ ├── 预操作状态
│ └── 重置功能
│
├── PDO通信
│ ├── RPDO1-4 (接收)
│ ├── TPDO1-4 (发送)
│ └── 事件驱动/同步触发
│
├── SDO服务
│ ├── 对象字典读取
│ ├── 对象字典写入
│ └── 错误处理
│
├── 心跳机制
│ ├── 可配置时间
│ └── 自动状态报告
│
└── SYNC同步
├── SYNC帧接收
└── 同步TPDO发送
| 类型 | COB-ID | 示例(ID=1) |
|---|---|---|
| NMT | 0x000 | 0x000 |
| SYNC | 0x080 | 0x080 |
| TPDO1 | 0x180+ID | 0x181 |
| TPDO2 | 0x280+ID | 0x281 |
| TPDO3 | 0x380+ID | 0x381 |
| TPDO4 | 0x480+ID | 0x481 |
| RPDO1 | 0x200+ID | 0x201 |
| RPDO2 | 0x300+ID | 0x301 |
| RPDO3 | 0x400+ID | 0x401 |
| RPDO4 | 0x500+ID | 0x501 |
| SDO请求 | 0x600+ID | 0x601 |
| SDO响应 | 0x580+ID | 0x581 |
| Heartbeat | 0x700+ID | 0x701 |
┌────────────────────────────────────────────────────┐
│ CANopen从站设备测试 │
├────────────────────────────────────────────────────┤
│ 设备信息 │
│ ├─ 节点ID: 1 │
│ ├─ 状态: Operational │
│ └─ 运行状态: 运行中 │
├────────────────────────────────────────────────────┤
│ 控制 │
│ [启动从站] [停止从站] │
│ [发送TPDO1] [发送TPDO2] [发送所有TPDO] │
├────────────────────────────────────────────────────┤
│ 心跳配置 │
│ 心跳时间(ms): [100 ▼] [配置心跳] │
├────────────────────────────────────────────────────┤
│ 日志 │
│ ┌────────────────────────────────────────────────┐ │
│ │ [15:30:45.123] CANopen从站测试程序已启动 │ │
│ │ [15:30:50.456] ✓ 从站启动成功 │ │
│ │ [15:30:55.789] ← 收到RPDO1: 12 34 56 78 │ │
│ │ [15:31:00.012] → 已发送TPDO1 │ │
│ │ ... │ │
│ └────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
// 定期通过TPDO发送传感器数据
slave.OnNmtStateChanged += (old, state) => {
if (state == NmtState.Operational) {
StartSensorPolling();
}
};
// 处理主站发送的控制命令
slave.OnRpdoReceived += (id, num, data) => {
if (num == 1) {
ExecuteCommand(data[0], data[1]);
}
};
// 通过SDO动态配置参数
slave.OnSdoWriteRequest += (id, idx, subIdx, val) => {
if (idx == 0x2000) {
UpdateCustomParameter(val);
}
};
Q: 启动失败怎么办?
A: 检查controlcan.dll是否存在,USBCAN2是否连接,CAN总线是否正确接线。
Q: 如何修改节点ID?
A: 在代码中修改:new CanOpenSlaveDevice(nodeId: 5)
Q: 收不到RPDO?
A: 确认COB-ID配置、从站状态、波特率设置是否与主站一致。
Q: 如何自定义TPDO数据?
A: 需要扩展SendTpdo方法,添加自定义数据参数。
更多问题请查看 README.md 的"常见问题"章节。
README.mdQUICKSTART.mdIMPLEMENTATION_SUMMARY.mdbin\Debug\Nameless.eds本项目仅供学习和研究使用。
版本: v1.0
更新日期: 2026-05-09
开发工具: Lingma (灵码) - Alibaba Cloud
祝您使用愉快! 🎉