如何编写一个CanOpen协议栈?

3
我有一个类似的问题。如何编写一个简单的CANopen协议层。 我阅读了答案,但是我必须自己编写一个CANopen协议层,而不能获得商业版。那么,有关编写CANopen栈(或层,我不确定区别)的基础知识是否存在?我甚至不知道从哪里开始。。。
如果需要的话,这里有一些信息:
我的主设备是带有QNX的Beagle Bone Black。QNX有一个通用的CAN库,但不特定于CANopen。而我的从设备是一个军用无刷电机控制器。我使用C++编写。 我有一份有关系统通用要求的文档。 有2个RPDO和4个TPDO,传输是同步的,没有停止模式(因此没有心跳和节点保护),所有的消息信息都被说明(大小、格式、相关节点ID等)。

2
我非常确定这个问题会被视为“过于宽泛”或“不相关”。简单的答案是,你需要获取协议规范文档并实现它 - 没有更多可说的了。这不是一个编程问题,而更像是一个系统工程问题。https://www.can-cia.org/standardization/specifications/ - Clifford
3个回答

22

实际上,至少有四个开源项目实现了CANopen协议:

  • CanFestival是最古老、可能也是最成熟的解决方案。许可证:LGPLv2。
  • CANopenNode旨在为微控制器提供服务。许可证:GPLv2。
  • Lely CANopen是用于实现CANopen主机和从机的库。许可证:Apache版本2。
  • openCANopen是在Linux上运行的主机。许可证:ISC。注意:本人是该项目的作者。

我本来想加链接的,但显然我没有足够的“声望”。

openCANopen还包括一些实用程序,例如将流量转发到TCP的守护程序以及解释并转储CANopen流量到标准输出的程序。

Lely CANopen的代码质量相当不错,如果在我开始编写自己的实现时它已经可用,我可能会使用它。然而,我没有尝试过使用它,因此我无法真正判断哪个实现更好。我只能说它们是不同的,其中一个可能更适合您的需求。

现在,我怀疑这些实现中没有一个可以直接在QNX上使用。它们必须进行调整,或者您可以将代码的个别部分复制到自己的实现中。至少这样可以节省一些时间。


CANOpenNode也可在任何具有SocketCan的通用Linux上使用。它的Linux实现称为CANopenSockets。它非常容易进行交叉编译,并使其适用于您的SBC。但我想知道它与各种闭源CANOpen库(如Emtas-CANopen、Port CANopen、PEAK等)相比如何。 - Geoffrey VL
1
嵌入式办公现在也有一个开源实现,使用Apache 2.0许可证。https://github.com/embedded-office/canopen-stack - Simon Byholm
@SimonByholm 你知道我能否在任何地方找到嵌入式办公套件的实现驱动程序吗? - Max
@Max 对不起回复晚了,但这可能是他们在Embedded Office赚钱的地方。他们将作为咨询服务为您编写驱动程序。您可以从其他免费堆栈中获取驱动程序并更改API以使其适合您的需求。 - Simon Byholm
1
请注意,CANopenNode现在是Apache 2.0许可证,https://github.com/CANopenNode/CANopenNode/blob/master/LICENSE - Chris Morgan

12

一种简单粗暴的解决方法是只实现最基本的功能(不要将其市场化或声称符合CANopen):

  • 支持其他节点将发送/期望接收的特定RPDOs / TPDOs。使用固定的COBID(CAN标识符)。忘记PDO映射和PDO配置,使用固定设置。
  • 实现NMT引导消息。
  • 在预操作和操作状态之间实现NMT状态转换(您的节点需要对此进行响应)。
  • 实现一些设置节点ID的方法。最简单的方法可能是将其硬编码为程序常量。

如果你很幸运,这就是所需的全部内容。如果你很不幸,那么可能会涉及SDO通信,这意味着你必须实现SDO协议以及整个对象字典。否则,以上内容相当简单直接,工作量不是很大。

如果你需要对象字典,那么可能没有其他办法除了获取完整的协议栈。你还需要向CAN-in-Automation申请供应商ID,但这是一次性费用(无版税)。


1
我也同意这种极简主义的“非CANopen兼容”的方法有时可能是最适合的解决方案。 - Oliver Heggelbacher
我甚至认为“仅使用SDO通信”是更容易的方法。对于标准的CANopen伺服驱动器,您只需要通过CANopen(“快速SDO传输”)编写和读取整数值。每次读写都是对驱动器请求的一个CAN总线帧,并且评估一个CAN总线帧以得到回复。 - Oliver Heggelbacher
2
@OliverHeggelbacher SDO通信应该只在预操作模式下进行。一个控制系统在预操作模式下允许其输出受到影响是有问题的设计。此外,SDO通信也需要稍微更多的开销数据流量,无论是否加快。设计控制系统的实践不是基于请求发送的基础工作,也不是根据数据变化发送(异步PDO/DS401默认行为),而是使用“事件定时器PDO”,每_n_毫秒在操作模式下发送它们的数据。 - Lundin
当然,所有这些都取决于系统,但像伺服驱动器这样的控制系统可能是高完整性系统,那么我期望的就是“事件计时器”行为,因为在这种应用中,这是唯一可接受的方法。 - Lundin
你好Lundin,你提出了关于正确设计遵循CANopen标准的系统进行周期性/时间关键的数据交换的非常有效的观点。我只是建议真正看看实际应用:主控制器可能不是PLC而是定制软件的Windows PC,该软件与单个驱动器通信,用于非动态甚至半手动定位目的。因此,在“预操作”状态下保持SDO并且不涉及NMT和PDO在我看来是一个有效的解决方案,易于实现、测试和调试。 - Oliver Heggelbacher

1
我来自嵌入式办公室,虽然有些晚了,但我仍想为您的搜索做出贡献。首先,我想提到的是,我们没有将驱动程序放入canopen-stack存储库的原因是嵌入式软件开发在多个目标平台和多个编译器上的复杂性,以及我提供尽可能运行软件的目标。仅凭库很难在使用过程中确定问题。
好消息是,我建立了一个环境,使不同的目标平台和编译器可以由单个维护者(即我)管理。因此,canopen-stack是使用LLVM在主机上开发的,并为STM32F7xx微控制器提供了第一个演示。更多内容即将推出,请保持关注 :-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接