文章目录
前言
从理论到源码。计划分两篇完成,基础篇和代码篇。
剩余篇已更新到个人博客,比较忙,没时间同步到CSDN,github首页链接
更新日期 2022年5月10日
欢迎批评指正
资源失效请联系 nowhitegive@foxmail.com
基础知识
该章节旨在理解需要的基础知识,后续章节会结合源码详细说明。
CAN总线
CAN 全称为Controller Area Network,即控制器局域网,由德国Bosch 公司最先提出,是国际上应用最广泛的现场总线之一。CAN 是一种多主方式的串行通讯总线,基本设计规范要求有高的位速率、高抗电磁干扰性,而且要能够检测出总线的任何错误。当信号传输距离达10Km 时CAN 仍可提供高达50Kbit/s 的数据传输速率。CAN 具有十分优越的特点:
A、较低的成本与极高的总线利用率;
B、 数据传输距离可长达10Km,传输速率可高达1Mbit/s;
C、可靠的错误处理和检错机制,发送的信息遭到破坏后可自动重发;
D、节点在错误严重的情况下具有自动退出总线的功能;
E、报文不包含源地址或目标地址仅用标志符来指示功能信息和优先级信息;
总线工作示意图:(详细可参照链接,不再赘述)
CANOpen
2.1 简介
CANopen是一种架构在控制局域网路(Controller Area Network, CAN)上的高层通讯协定,包括通讯子协定及设备子协定常在嵌入式系统中使用,也是工业控制常用到的一种现场总线。由非营利组织CiA(CAN in Automation)进行标准的起草及审核工作,基本的 CANopen 设备及通讯子协定定义在 CAN in Automation (CiA) draft standard 301中。针对个别设备的子协定以 CiA 301 为基础再进行扩充。如针对 I/O 模组的 CiA401 及针对运动控制的 CiA402。
CANopen 实现了OSI模型中的网络层以上(包括网络层)的协定。CANopen 标准包括寻址方案、数个小的通讯子协定及由设备子协定所定义的应用层。 CANopen 支持网络管理、设备监控及节点间的通讯,其中包括一个简易的传输层,可处理资料的分段传送及其组合。一般而言数据链结层及物理层会用CAN来实作。除了 CANopen 外,也有其他的通讯协定(如EtherCAT)实作 CANopen 的设备子协定。
简言之,CAN是物理层和数据链路层,CANOpen是调用CAN进行通行的应用层。详细可参照链接。
CANOpen入门推荐周立功教程,个人笔记版本,后续将围绕该文档展开,对照学习(后文对此文档简称canez)。
2.2 帧ID/COB-ID
帧ID,顾名思义,是每一帧报文的身份识别码。通过帧ID即可判断该报文的类型以及目标节点。在CANOpen协议中已经预定义好了绝大部分需要用到的变量,例如心跳,波特率,序列号等。参照canez p6(表4.1)以及p8(表4.2)。除了预定义的之外,开发者还可以自定义COB-ID的作用,虽然几乎用不到,但是在开发时还是要双方协商好,避免冲突。
CANOpen以主从模式运行,每条总线仅运行有一个主节点存在,从节点可达127。每个节点都应该有互异的节点ID,即NODE-ID。 CANOpen报文结构为COB-ID + 数据长度 + 数据。
COB-ID包含了该报文功能码以及目标节点的NODE-ID。例如canez p8(表4.2)中182h表示该报文功能为TPDO1,目标节点ID为2。
2.3 NMT
NMT全称Network Management-Master,意为网络管理主机(参照canez p16)。一条总线中有且仅有一个主节点。主节点通过NMT命令可控制各个从节点的状态、监测各个节点等。节点状态转换按照canez p17(图6.2)进行转换。
NMT命令帧ID为00h。数据段中包含了需要控制的目标ID。
NMT讲解canez p17已经非常详细,不再赘述。后续章节会结合源码进行详细讲解。至此只需理解NMT命令的内容以及作用即可。
2.4 PDO
上文说过CANOpen以主从模式运行,此外,还遵循生产消费模型。生产消费模型可以简单理解为一个发送数据,一个接收数据,发送数据的一方叫生产者,接收数据的叫消费者。
PDO通信参照canez p22。其中较难理解的映射参数将在后文结合源码讲解,更容易理解。
PDO通信一共预定义了四个。每个PDO有一对RPDO和TPDO,在编辑字典时,根据双方协定,设置发送类型,将需要传输的数据变量在PDO项中预设,发送方调用TPDO,接收方通过RPDO的参数变量获得值。注意:收发是以节点自身为参考。PDO无需应答,适合数据的大量传输。状态机转为操作态才可开启PDO传输,其余状态下PDO关闭。
2.5 SDO
参照canez p26。
简言之,SDO可以读写字典中的数据。问的数据中包含索引和子索引等参数,目标节点即可根据问的报文中索引与子索引指向的数据返回。SDO一般用于从站的参数配置,或者变量读取。SDO命令在预操作态、操作态、停止态均可发送。
2.6 同步协议SYNC
同步命令SYNC(参见canez p30)帧ID为80h。
该命令主要作用就是同步各个节点的网络传输(主要是PDO),上文PDO中提到设置发送类型,即可设置为每间隔n个SYNC报文主动发送一次PDO。SYNC一般由主节点发送,在字典编辑器中可以设置发送的间隔时间。例如主站每间隔20ms发送一个SYNC,从站A每间隔3个SYNC发送一次TPDO1,每间隔4个SYNC发送一次TPDO2。这些参数都是在字典编辑器中编辑的,也可以主站通过SDO修改。
2.7 时间戳Time-stamp
时间戳帧ID为100h,数据长度为6个字节。
在canopen协议中,时间戳以32+16位方式发送储存,前32位表示当日的ms数,后16位表示距离1984.1.1的天数。例如 时间戳数据段为0x 12 34 56 78 9A BC 。则前32位正确顺序为0x78 56 34 12 表示毫秒,后16位0xBC9A表示天数。
周立功提供了时间戳转换源码(canez p32),亦可以自行转换。
2.8 紧急报文EMCY
紧急报文帧ID为80h+NODE-ID(参照canez p33)。当从站发生特定错误时,可发送紧急报文,报文中包含canopen协议预定义的错误代码或者用户自定义的错误码,主站即可接收到错误信息并做出相应处理动作。
CanFestival
3.1 简介
CanFestival提供了将CANOpen运行起来的源码以及字典编辑器。可以理解为canopen是一个协议,而canfestival是将canopen运行起来的协议栈,该协议栈开源,并且提供字典编辑器的脚本,后文对应章节会详细介绍并提供源码等链接。
3.2 字典编辑器
对象字典本质是一个结构体,亦可以理解为一个数据库,其中存放了所有通过CANOpen协议的数据。内部根据CANOpen协议预设了许多参数变量,例如节点ID、节点状态、波特率,这些变量可在对象字典编辑器中修改、添加或者删除。对每一个CANOpen设备来说,对象字典是其数据储存的容器,正如名字一样,该结构体储存的数据可以通过SDO读写索引位置数据。
索引为两个字节,0x0000~0xffff。canopen协议对索引做了预定义:
对部分索引如果需要存放多个数据,便有了子索引,子索引为一个字节:
对象字典包括由字典编辑器生产的.c和.h文件,以及字典配置文件。
字典编辑器为python脚本,运行后可新建编辑字典文件(修改字典时必须有.od配置文件),并生成.c和.h的源码文件,可直接替换之前的文件。开发过程中应该规范命名变量,方便后续开发。
字典编辑
协议栈的运行,字典的作用至关重要。此章节将会着重介绍字典如何新建、编辑以及字典的结构组成。
canfestival协议栈具有很多版本,不同版本之间源码可能会有区别,字典编辑器的版本需要与字典文件和源码对应。提供最新版,版本号为CanFestival-3-de1fc3261f21。该文件中包含了canfestival的字典编辑器、RTT的CANOpen修复版本(该版本可以直接运行)以及编辑器运行需要的软件。
1 安装环境
字典编辑器需要安装python,如果已经安装python3,需要卸载,否则会出现未知错误。如果后续步骤无法进行,建议卸载现有python,安装上述文件中的软件,如下图所示。
安装完成之后打开下图文件。注:从官网下载的源码需要解压某压缩包,上述链接提供的版本已经解压完成。
如果能出现下图,则说明环境配置完成,否则需要按照上述步骤重新配置。
2 新建节点字典文件
- 新建文件,选择节点是从站还是主站,右侧根据需要选择节点网络管理类型,节点守护或者心跳,一般情况下建议使用心跳。
-
输入节点名称,选择网络管理类型。
图中DS-4xx文件协议属于行业特定协议,如401为伺服电机控制协议,若节点需要控制伺服电机,即可选择该协议。字典中有厂商自定义区域,不同行业在该区域订立标准,形成上述的多种协议。
-
确定之后即可进入到字典编辑。如下图所示,左侧0x0001-0xBfff即为索引。右侧即为该索引块对应的功能。
3 *字典索引块介绍
-
0x0001-0x0fff
该区域大部分为保留区域,无法编辑,能力有限,原因尚不清楚,知晓请发邮。其他为数据类型定义。 -
0x1000-0x1029
该区域为从站节点的一些基本属性,例如心跳时间,硬件/软件版本号等等。如果需要添加则按左下角选择之后添加即可。
-
0x1200-0x12ff
该区域为SDO数据块,存放SDO主从的参数。在此添加或者删除SDO通道。 -
0x1400-0x15ff
该区域为RPDO基础参数区域,即特质化某个RPDO的属性。其中包括了传输类型、生产禁止时间、开始传输的SYNC值等等。每个RPDO根据实际需要设置参数。在这里只是开启了RPDO的传输通道,并且配置了某个RPDO是如何工作的,但是没有涉及到接收到的数据应该存放在何处或者变量名称。这一部分内容是在后续索引中编辑的。
-
0x1600-0x17ff
该区域即为RPDO的映射区域。上面提到RPDO的数据接收存放问题即在此编辑。每添加或者删除一个RPDO,字典编辑器会在此自动添加或者删除一个PDO映射。简言之,当我们在上一步骤中添加或者删除一个RPDO,字典编辑器会在此区域自动添加或者删除一个RPDO映射。每个映射中数据的个数、值需要我们自己编辑。subindex即为子索引,箭头所指的数字8是该RPDO接收的数据个数,最下方箭头所指内容即为需要接收的数据。图中只有一个选项是因为这部分内容在后面的自定义区域编辑,后续会讲到。只需知道在这里选择需要接收的数据即可。
-
0x1800-0x19ff
结构与0x1400-0x15ff相似,只是该区域设置的是TPDO的参数。 -
0x1a00-0x1bff
结构与0x1600-0x17ff相似,该区域设置的是TPDO的映射。 -
0x1c00-0x1fff
该区域在此编辑器中无法编辑,可能需要其他编辑器才能编辑,如有请邮我。 -
0x2000-0x5fff
该区域即为自定义传输的地图变量。该编辑器提供了三种数据类型,一是单一变量,二是数组,三是多变量集合。变量在字典文件中定义为全局变量。
**添加单一变量:type选择var
添加之后可以在type中选择数据类型,如u8,u16等。
**添加数组变量:类型选择array
输入数组成员的个数
数组中所有元素的数据类型都是一样的,只能在子索引为1的位置修改,如下图所示。
数组成员的value值可以预设,也可以在程序中赋值。
**添加变量集合:type选择REC
该方法与数组方法不同,首先数组方法各成员变量名称无法自定义,其次数组方法成员变量类型全部一致。该方法可以自命名各个变量名称,并且选择各个变量的数据类型。如下图所示。
添加数据之后,在RPDO或者TPDO的mapping中即可选择需要传输的数据。注意:如果想要通过PDO传输数据,那两个节点的RPDO与TPDO应该对应,即接收方的RPDO接收的数据与发送方TPDO地图(Mapping)中映射的的数据以及数据类型都应一一对应,协议栈会自动将接收到的数据一一对应并赋值,无需接收后手动分解报文解码。
-
0x6000-0xbfff
行业自定义区域,例如伺服电机的DS401在该区域定义了许多变量用以存放数据,例如线圈数,最大转速,当前位置等等。这些都是由组织统一规范制定的。