从 OSI 的 7 层网络模型的角度来看同,CAN(Controller Area Network)现场总线仅仅
定义了第 1 层(物理层,见 ISO11898-2 标准)、第 2 层(数据链路层,见 ISO11898-1 标准);
而在实际设计中,这两层完全由硬件实现,设计人员无需再为此开发相关软件(Software)
或固件(Firmware),只要了解如何调用相关的接口和寄存器,即可完成对 CAN 的控制。
CAN 总线的工业自动化应用中,由于设备的互通互联
的需求越来越多,所以需要一个开放的、标准化的高层协议:这个协议支持各种 CAN 厂商设备的互用性、互换性,能够实现在 CAN 网络中提供标准的、统一的系统通讯模式,提供设备功能描述方式,执行网络管理功能。其中包括:
应用层(Application layer):为网络中每一个有效设备都能够提供一组有用的服务与协议。
通讯描述(Communication profile):提供配置设备、通讯数据的含义,定义数据通讯方式。
设备描述(Device proflile):为设备(类)增加符合规范的行为。
CAN 标准帧格式 即 11bit 的 ID 域,以尽量减小传输时间;
网络管理(NMT)如下图:
NMT 主机和 NMT 从机之间通讯的报文就称为 NMT 网络管理报文。网络管理中,同一个网络中只允许有一个主节点、一个或多个从节点,并遵循主从模式。
为了协调各个节点的同步、心跳、时间、错误提示等通讯控制,CANopen 还定义了一系列特殊协议(Special protocols)报文。如表 4.1 所示,为 CANopen 预定义报文(Pre-defined CAN-IDs)的 NMT 报文和特殊协议报文。
PDO 和 SDO 的通讯区别在于,PDO 属于过程数据,即单向传输,无需接收节点回应CAN 报文来确认,从通讯术语上来说是属于“生产消费”模型。如图 4.4 所示。
SDO 属于服务数据,有指定被接收节点的地址(Node-ID),并且需要指定的接收节点回应 CAN 报文来确认已经接收,如果超时没有确认,则发送节点将会重新发送原报文。这种通讯方式属于常见的“服务器客户端”的通信模型,即我们通常所说的轮询式。如图 4.5所示。
PDO 和 SDO 的报文 ID 分配该分配表是基于 11 位 CAN-ID 的标准帧格式。将其划分为 4 位的功能码(Function-ID)和 7 位的节点号(Node-ID)。如图 4.6 所示
在 CANopen 里也通常把 CAN-ID 称为 COB-ID(通信对象编号)。它与Node-ID无必然联系。,但在过程数据对象(PDO)和服务数据对象(SDO)中,COB-ID 中包含了 Node-ID。
PDO 分为 TPDO(发送 PDO) 和(接收 RPDO),发送和接收是以 CANopen 从站节点为参考(如果 CAN 主站就相反)。TPDO和 RPDO 分别有 4 个数据对象,每种数据对象就是 1 条 CAN 报文封装,如表 4.2 所示,
SDO 就相对比较简单固定,发起通讯的“问”SDO 的 CAN 帧 ID 就是 600h +node-ID,这里的 Node-ID 是被问的节点地址,而被问的节点应“答”SDO 的 CAN 帧 ID 就是 580h +node-ID。
CANopen 对象字典(OD: Object Dictionary),对象字典就是一个有序的对象组,描述了对应 CANopen 节点的所有参数,包括通讯数据的存放位置也列入其索引,这个表变成可以传递形式就叫做 EDS 文件(电子数据文档Electronic Data Sheet)。对象字典,就像体检表,具备这个人每个功能的参数,便于用人单位(主站)进行合理分配工作。
每个对象采用一个 16 位的索引值来寻址,这个索引值通常被称为索引,其范围在 0x0000到 0xFFFF 之间。为了避免数据大量时无索引可分配,所以在某些索引下也定义了一个 8 位的索引值,这个索引值通常被称为子索引,其范围是 0x00 到 0xFF 之间。
每个索引内具体的参数,最大用 32 位的变量来表示,即 Unsigned32,四个字节。
每个 CANopen 设备都有一个对象字典,使用电子数据文档(EDS 文件)来记录这些参数,而不需要把这些参数记录在纸上。对于 CANopen 网络中的主节点来说,不需要对CANopen 从节点的每个对象字典项都访问。
5.1 所示,为对象字典索引区域定义,其中标绿色底纹的通讯对象子协议区和制造商特定子协议区是用户需要关注的区域。
(Communication profile area)通讯对象子协议区(Communication profile area)定义了所有和通信有关的对象参数,如表 5.2 所示,标绿色底纹的索引范围 1000h to 1029h为通用通讯对象,所有 CANopen 节点都必须具备这些索引,否则将无法加入 CANopen 网络。其他索引根据实际情况进行分配与定义。
由于通用通讯对象十分重要,NMT 主站(CANopen 主站)在启动时,通常都全部或者部分读取所有从站中通用通讯对象中的索引,所以所有的通用通讯对象都必须在CANopen 从站中实现,使用者也必须熟知这些索引地址与其含义。如表 5.3 所示。
对象字典索引 2000h to 5FFFh为制造商特定子协议,通常是存放所应用子协议的应用数据。而上文所描述的通讯对象子协议区(Communication profile area)是存放这些应用数据的通信参数。比如广州致远电子的 XGate-COP10 从站模块规定了:
RPDO 的通讯参数存放在 1400h to 15FFh 映射参数存放在 1600h to 17FFh 数据存放为
2000h 之后厂商自定义区;
TPDO 的通讯参数存放在 1800h to 19FFh 映射参数存放在 1A00h to 1BFFh 数据存放为
2000h 之后厂商自定义区。
标准化设备子协议,为各种行业不同类型的标准设备定义对象字典中的对象。目前已有十几种为不同类型的设备定义的子协议,例如 DS401、DS402、DS406 等,其索引值范围为 0x6000~0x9FFF。同样,这个区域对于不同的标准化设备子协议来说,相同的对象字典项其定义不一定相同。
每个 CANopen 从节点的 CANopen 协议栈中,必须具备 NMT 管理的相应代码,这是节点具备 CANopen 协议的最基本的要素。
NMT 管理涉及到一个 CANopen 节点从上电开始的 6 钟状态,包括:
初始化(Initializing):节点上电后对功能部件包括 CAN 控制器进行初始化;
应用层复位(Application Reset):节点中的应用程序复位(开始),比如开关量输出、模拟量输出的初始值;
通讯复位(Communication reset):节点中的CANopen通讯复位(开始),从这个时刻起,此节点就可以进行CANopen通讯了。
预操作状态(Pre-operational):节点的CANopen通讯处于操作就绪状态,此时此节点不能进行PDO通信,而可以进行SDO进行参数配置和NMT网络管理的操作;
操作状态(operational):节点收到NMT主机发来的启动命令后,CANopen通讯被激活,PDO通信启动后,按照对象字典里面规定的规则进行传输,同样SDO也可以对节点进行数据传输和参数修改;
停止状态(Stopped):节点收到NMT主机发来的停止命令后,节点的PDO通信被停止,但SDO和NMT网络管理依然可以对节点进行操作;
除了初始化状态,NMT主机通过NMT命令可以让网络中任意一个的CANopen节点
进行其他5种状态的切换。如图 6.2所示。
当然CANopen节点也可以程序自动完成这些状态的切换。
任何一个 CANopen 从站上线后,为了提示主站它已经加入网络(便于热插拔),或者避免与其他从站 Node-ID 冲突。这个从站必须发出节点上线报文(boot-up),如图 6.3 所示,节点上线报文的 ID 为 700h+Node-ID,数据为 1 个字节 0。生产者为 CANopen 从站。
为了监控 CANopen 节点是否在线与目前的节点状态。CANopen 应用中通常都要求在线上电的从站定时发送状态报文(心跳报文),以便于主站确认从站是否故障、是否脱离网络。
如图 6.4所示,为心跳报文发送的格式,CANID与节点上线报文相同为700h+Node-ID,数据为 1 个字节,代表节点目前的状态,04h为停止状态,05h为操作状态,7Fh为预操作状态。
CANopen 从站按其对象字典中 1017h 中填写的心跳生产时间(ms)进行心跳报文的发送,而 CANopen 主站(NMT 主站)则会按其 1016h 中填写的心跳消费时间进行检查,假设超过诺干次心跳消费时间没有收到从站的心跳报文,则认为从站已经离线或者损坏。
NMT 网络管理中,最核心的就是 NMT 节点状态切换命令,这是 NMT 主站所进行网络管理的“命令”报文。使用者必须牢记这些命令。
CANID 均为 000h,具备最高的 CAN 优先级。数据为 2 个字节:
第 1 个字节代表命令类型:
01h为启动命令(让节点进入操作状态);
02h为停止命令(让节点进入停止状态);
80h为进入预操作状态(让节点进入预操作状态);
81h为复位节点应用层(让节点的应用恢复初始状态,比如列车门都恢复打开状态);
82h为复位节点通讯(让节点的 CAN 和 CANopen 通讯重新初始化,一般用于总线收到
干扰,导致节点总线错误被动,或者总线关闭时)。
第二个字节代表被控制的节点 Node-ID,
如果要对整个网络所有节点同时进行控制,则这个数值为 0 即可。
如图 6.5 所示,
需要具备以下功能:
支持 PDO、SDO 发送与接收;
支持 NMT 网络管理;
支持 PDO 通信类型并能够支持监控每一个 PDO 目标;
LSS 层设置功能:从站波特率设置、从站节点编号设置;
支持从站管理功能:类型与名称读取、对象字典读写;
紧急报文发送功能;
扩展 CANopen 标准指示灯功能
PDO 通信参数,定义了该设备所使用的 COB-ID、传输类型、定时周期等。RPDO 通讯参数位于对象字典索引的 1400h to 15FFh,TPDO 通讯参数位于对象字典索引的 1800h to19FFh。每条索引代表一个 PDO 的通信参数集,其中的子索引分别指向具体的各种参数。如表 7.2 所示。
Number of entries 参数条目数量:即本索引中有几条参数;
COB-ID:即这个 PDO 发出或者接收的对应 CAN 帧 ID;
发送类型:即这个 PDO 发送或者接收的传输形式,通常使用循环同步和异步制造商特定事件较多;
Inhibit time 生产禁止约束时间(1/10ms):约束 PDO 发送的最小间隔,避免导致总线负载剧烈增加,比如数字量输入过快,导致状态改变发送的 TPDO 频繁发送,总线负载加大,所以需要一个约束时间来进行“滤波”,这个时间单位为 0.1ms;
Event timer 事件定时器触发的时间(单位 ms):定时发送的 PDO,它的定时时间,如果这个时间为 0,则这个 PDO 为事件改变发送。
SYNC start value 同步起始值:同步传输的 PDO,收到诺干个同步包后,才进行发送,这个同步起始值就是同步包数量。比如设置为 2,即收到 2 个同步包后才进行发送。
PDO 映射参数是初学者学习 CANopen 时的一个难点,它包含了一个对象字典中的对象列表,这些对象映射到相应的 PDO,其中包括数据的长度(单位,位),对于生产者和消费者都必须要知道这个映射参数,才能够正确的解释 PDO 内容。就是将通信参数、应用数据和具体 CAN 报文中数据联系起来。
RPDO 通讯参数 1400h to 15FFh,映射参数 1600h to 17FFh,数据存放为 2000h 之后厂商自定义区域;TPDO 通讯参数 1800h to 19FFh,映射参数 1A00h to 1BFFh,数据存放为 2000h 之后厂商自定义区域。
表 7.3 模拟 TPDO1,将参数、应用数据、CAN 报文数据联
合起来展示,不同的映射采用不同的颜色。
SDO 主要用于 CANopen 主站对从节点的参数配置。服务确认是 SDO 的最大的特点,为每个消息都生成一个应答,确保数据传输的准确性。
在一个 CANopen 系统中,通常 CANopen 从节点作为 SDO 服务器,CANopen 主节点;作为客户端(称为 CS 通讯)。SDO 客户端通过索引和子索引,能够访问 SDO 服务器上的对象字典。这样 CANopen 主节点可以访问从节点的任意对象字典项的参数,并且 SDO 也可以传输任何长度的数据(当数据长度超过 4 个字节时就拆分成多个报文来传输)。
SDO 的通讯原则非常单一,发送方(客户端)发送 CAN-ID 为 600h+Node-ID 的报文,其中 Node-ID 为接收方(服务器)的节点地址,数据长度均为 8 字节;
接收方(服务器)成功接收后,回应 CAN-ID 为 580h+Node-ID 的报文。这里的 Node-ID依然是接收方(服务器)的节点地址,数据长度均为 8 字节。如图 8.2 所示。
最常用最常见的 SDO 协议是快速 SDO,所谓快速,就是 1 次来回就搞定。前提是读取和写入的值不能大于 32 位。如图 8.3 所示,为快速 SDO 协议的示意图。命令中直接包含了 要读写的索引、子索引、数据。可谓直接命中。
快速 SDO 的难点在于 CS 命令符的记忆,需要读者收藏这个示意图。
当需要传输的值超过 32 位时,就不能使用快速 SDO 传输。必须使用
普通 SDO 进行分 帧传输。在应用中较少用到,一般用于 CANopen 节点的程序固件升级,或者做网关转换MVB 总线之类数据最大可达 256 位的应用。
普通SDO的CAN帧ID与快速SDO相同,依然发送方(客户端)发送的报文CAN-ID为 600h+Node-ID,接收方(服务器)成功接收后,回应 CAN-ID 为 580h+Node-ID 的报文。
同步(SYNC),该报文对象主要实现整个网络的同步传输。
每个节点都以该同步报文作为 PDO 触发参数,因此该同步报文的 COB-ID 具有比较高的优先级以及最短的传输时间。 一般选用 80h作为同步报文的 CAN-ID,如图 9.2 所示。
一般同步报文由 NMT 主机发出,CAN 报文的数据为 0 字节。但如果一个网络内有 2 个同步机制,就需要设置不同的同步节拍,比如某些节点按 1 个同步帧发送 1 次 PDO,其 他的节点收到2个同步帧才发送1此PDO,所以这里PDO参数中的同步起始值就起了作用。
在同步协议中,有 2 个约束条件:
同步窗口时间:索引 1007h约束了同步帧发送后,从节点发送 PDO 的时效,即在这个时间内发送的 PDO 才有效,超过时间的 PDO 将被丢弃;
通讯循环周期:索引 1006h规定了同步帧的循环周期
时间标记对象(Time Stamp),NMT 主机发送自身的时钟,为网络各个节点提供公共的时间参考,即网络对时。
时间戳协议采用广播方式,无需节点应答,CAN-ID 为 100h,数据长度为 6,数据为当 前时刻与 1984 年 1 月 1 日 0 时的时间差。如图 9.4 所示。节点将此时间存储在对象字典 1012h 的索引中。
由于时间换算起来非常费劲,这里特地准备好了换算函数,方便读者使用。
void DataTime(void)
{
uint32 n,i,da;
canopen_data;//定义网络的日期;
canopen_msecond;//定义网络的时间(ms)
/*计算年*/
n= (canopen_data+671)/1461;//求有多少个 2 月 29 日
Year=(canopen_data-n)/365+1984;//得到年
if((canopen_data-n)%365==0){
Year=Year-1;
}
/*计算月日*/
if((Year%400==0)||(Year%4==0&&Year%100!=0))//判断闰年
{
m[2]=29;
}else{
m[2]=28;
}
da=canopen_data-((canopen_data-n)/365)*365-n;//减去该年前的前天,得到改年的第几天
for(i=0;i<12;i++)
{
if(da>m[i])
{
da=da-m[i];//让天数减去每个月的天数
}
if(da==0)
{
Month=i+1;
Day=m[i+1];
}
if(da<=m[i+1]&&da!=0)//如果得到小于或等于该月的天数,则可以确定为哪一天
{
Month=i+1;
Day=da;
break;
}
}
/*计算时分秒*/
canopen_msecond=canopen_msecond/1000;//把毫秒转换为秒
Hour=canopen_msecond%(3600*24)/3600;
Minute=canopen_msecond%3600/60;
Second=canopen_msecond%60;
}
紧急事件对象(Emergency),是当设备内部发生错误,触发该对象,发送设备内部错误代码,提示 NMT 主站。紧急报文属于诊断性报文,一般不会影响 CANopen 通讯,其 CAN-ID存储在 1014h的索引中,一般会定义为 080h +node-ID,数据包含 8 个字节,如图 9.5 所示。
其中包括 EEC:紧急时间错误代码,ER:错误寄存器,MEF:厂商自定义的错误代码。当然这些都需要查表才能获知,进行诊断。
与 PDO 的生产禁止时间类似,紧急报文也有生产禁止时间,存储在对象字典的 1015h 中,为了限制节点不断发送紧急报文,导致总线负载过大。