一、引言
作为一个职场专业摸鱼人,泡个下午茶慢慢品来是日常中工作中的必修课了。前天喝茶之余思虑了一下,自己工作已经有几年了,每天忙碌的工作、撸不完的代码。人生短短几十年工作占据了生活大部,不能光为了碎银几两,总得留下点有意义的东西,积极入世才是生活的正能量,人生的道路有痕迹才能让回忆更丰满。刚好自己前一段时间工作中正好也用到canopen通信,那就从这里开始吧,希望自己的经验和认知能对各位有所帮助。
俗话说——手法怎么样,你得上了钟才知道。。哈哈(大家好我是迷糊君粉丝)。废话不多说,直接上干货,——>冲!!!
二、canopen协议概述
canopen是一个基于can串行总线的网络传输系统的应用层协议。网络中的不同设备节点通过对象字典来交换数据,其中主节点可以通过过程数据对象(PDO)或者服务数据对象(SDO)来获取或者修改其它节点对象字典列表中的数据。要理解canopen,首先要先来了解三个概念,分别是通信对象标识符、对象字典和通讯对象。
2.1 通信对象标识符
通信对象标识符(COB-ID)指定了在通信过程中对象的优先级及通信对象的识别。COB-ID与CAN2.0标准协议中的11位帧ID对应。11位COB-ID又由两部分组成,分别是4位的功能码和7位的节点地址。
![](https://img-blog.csdnimg.cn/direct/3c4381531a184e4880b1e3ade67437e9.png)
功能码 | nodeID(节点地址) | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
通讯对象 | 功能代码 | 节点地址 | COB-ID |
---|---|---|---|
网络管理 | 0000b | 0 | |
同步对象 | 0001b | 0 | 80h |
紧急报文对象 | 0001b | 1-127 | 80h+nodeID |
TPDO1 | 0011b | 1-127 | 180h+nodeID |
RPDO1 | 0100b | 1-127 | 200h+nodeID |
TPDO2 | 0101b | 1-127 | 280h+nodeID |
RPDO2 | 0110b | 1-127 | 300h+nodeID |
TPDO3 | 0111b | 1-127 | 380h+nodeID |
RPDO3 | 1000b | 1-127 | 400h+nodeID |
TPDO4 | 1001b | 1-127 | 480h+nodeID |
RPDO4 | 1010b | 1-127 | 500h+nodeID |
T_SDO | 1011b | 1-127 | 580h+nodeID |
R_SDO | 1100b | 1-127 | 600h+nodeID |
网络错误管理控制 | 1110 | 1-127 | 700h+nodeID |
2.2 对象字典
对象字典(OD:Object Dictionary)是CANopen协议核心部分,它是一组参数和变量的有序对象组,描述了对应canopen节点的所有参数。这个有序的集合变成可以传递形式就叫做EDS文件。每个对象采用一个16位的索引值来寻址,其范围在0x0000到0xFFFF之间,为了允许访问数据结构中的单个元素,同时定义了一个8位的子索引,其范围在0x00到0xFF之间,对象字典的结构参照下表。
索引 | 对象 |
0001h-0FFFh | Data Type Definition |
1000h-1029h | Communication Parameters |
1200h-12FFh | SDO Parameters |
1400h-15FFh | Receive PDO Parameters |
1600h-17FFh | Receive PDO Mapping |
1800h-19FFh | Transmit PDO Parameters |
1A00h-1BFFh | Transmit PDO Mapping |
2000h-5FFFh | Manufacturer Specific |
6000h-9FFFh | Standardized Device Profile |
A000h-FFFFh | Reserved |
2.3 常用的通信对象
1)网络管理对象-Network Management Objects(NMT)
网络管理对象heartbeat协议及NMT消息,基于主从通信模式,NMT用于管理和监控网络中的各个节点。
2)服务数据对象-Service Data Object(SDO)
·包括接收SDO(RSDO)和发送SDO(TSDO);
·通过使用索引、和子索引,SDO使客户端能够访问设备对象字典中的项;
·协议是确认服务类型,为每一个消息生成一个应答;
·SDO请求和应答报文总是8个字节;
·SDO允许传送任何长度数据,当数据超过8个字节时分拆成几个报文;
3)过程数据对象-Process Data Object(PDO)
·包括接收PDO(RPDO)和发送PDO(TPDO);
·用来传输实时数据,数据传送限制在1-8个字节;
·PDO传输包含异步和同步两种,由通信参数决定;
·PDO的消息内容是预定义的,由PDO映射参数决定;
4)同步对象-Synchronisation Object(SYNC)
同步对象是由CANOPEN主站周期地广播到CAN总线的报文,用来实现基本的网络时钟信号,每个设备可根据自己的配置决定是否使用该事件来跟网络中的其它设备进行同步通信。
5)紧急报文-Emergency Object(EMCY)
设备内部通信故障或者应用故障错误时发送的报文
三、网络管理系统
网络管理系统NMT(The network management)通过NMT对象执行NMT服务,通过NMT服务,can设备节点被初始化、启动、监控或复位。NMT遵循主从结构。
3.1 NMT状态切换
下图描述了canopen设备NMT状态切换流程图。从图上可以看出NMT状态主要有四种,分别为初始态、预操作状态、运行态和停止态。
序号 | 描述 |
1 | 上电后自动进入初始化模式 |
2 | 初始化后自动进入预操作状态 |
3 | 由NMT服务启动远程节点或者由设备本身控制启动节点 |
4、7 | 由NMT服务控制进入预操作状态 |
5、8 | 由NMT服务控制停止远程节点 |
6 | 由NMT服务控制启动远程节点 |
9、10、11 | 由NMT服务控制复位远程节点 |
12、13、14 | 由NMT服务控制复位远程节点的通信 |
a)NMT初始态,又分为三个子状态,分别为Initialising(初始化)、Reset application(复位应用)和Reset communication(复位通信)。初始化状态为设备上电或者硬件复位后的第一个状态,执行基本的canopen初始化后自动进入复位应用状态;在复位应用状态下,标准设备协议区参数和制造商特定协议区参数被赋予初值,之后进入复位通信状态;在复位通信状态下,通信参数区被赋予初值,然后canopen设备发送boot-up消息并进入预操作状态。
b)NMT预操作状态,在预操作状态,允许SDO通信,禁止PDO通信,此状态通常用于配置PDO的通信参数和映射参数等,然后设备可以由NMT启动远程节点服务或本地控制进入运行状态。
c)NMT运行态,此状态允许所有的通信服务。
d)NMT停止态,此状态下所有的通信服务被终止,包含EMCY也被挂起(除心跳和节点保护,如果被激活)。
上述NMT状态切换除部分由内部自动实现外,其余由NMT报文实现控制转换。
COB-ID | RTR | DATA | |
0 | 1 | ||
0x000 | 0 | 命令字 | nodeID |
命令字 | 说明 |
0x01 | 启动远程节点 |
0x02 | 停止远程节点 |
0x80 | 进入预操作状态 |
0x81 | 复位节点 |
0x82 | 复位节点通信 |
3.2 NMT boot-up
任何一个canopen从设备上线后,为了提示主站已经加入网络(便于热插拔)。这个从站必须发出节点上线报文(boot-up)。报文格式如下,COB-ID为0x700+nodeID,数据长度为1个字节且数据为0。
3.3 NMT错误控制
NMT网络监控主要用于检测网络中的设备是否在线和设备所处的状态,包含节点保护和心跳,两者不能同时使用。
1、节点保护
节点保护是NMT主机通过远程帧,周期的查询网络中从机的状态。节点保护遵循主从模型,每个远程帧都必须得到应答。与节点保护相关的对象包含保护时间(单位ms)100Ch和寿命因子100Dh,100Ch和100Dh的乘积决定了主机查询的最迟时间。
COB-ID | RTR |
0x700+nodeID | 1 |
COB-ID | RTR | DATA |
0x700+nodeID | 0 | 状态字 |
数据位 | 说明 |
Bit7 | 必须在每次交替中置0或者1 |
Bit6-Bit0 | 4-停止状态 5-操作状态 127-预操作状态 |
2、心跳
心跳模式采用的生产者-消费者模型。CANOPEN设备可根据生产者心跳间隔对象1017h设置的周期来发送心跳报文,一旦在消费者心跳时间范围内未接受到相应节点的生产者心跳,则认为该节点故障。
COB-ID | RTR | DATA |
0x700+nodeID | 0 | 状态字 |
四、服务数据对象
4.1 SDO传输框架
SDO传输方式遵循客户端-服务器模式,即一应一答方式。服务确认是SDO的最大特点 , 为每个消息都生成一应答,确保数据传输的准性。由CAN总线网络中的SDO客户端发起,SDO服务器做出应答。因此,SDO之间的数据交换至少需要两个CAN报文才能实现,且两个CAN报文的CAN标识符不一样。
发送方(客户端)发送COB-ID为600h+nodeID的报文,其中nodeID为接收方 (服务器)的节点地址 ,数据长度均为8字节;接收方(服务器)成功接收后,回应COB-ID为580h+nodeID的报文。这里的nodeID依然是接收方(服务器)的节点地址 ,数据长度均为8字节。
SDO的传输又分为不高于四个字节和高于四核字节的对象数据传输。不高于四个字节采用快速SDO传输方式,高于四个字节采用普通传输或叫做块传输方式。
4.2 快速SDO
快速SDO用于读写不大于四个字节的数据,一次交互就搞定。
COB-ID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
客户端 | 600h+ nodeID | 23h | 索引 | 子索引 | 数据 | |||||
27h | 数据 | |||||||||
2bh | 数据 | |||||||||
2fh | 数据 | |||||||||
服务器 | 正常 | 580h+ nodeID | 60h | 索引 | 子索引 | |||||
异常 | 80h | 错误代码 |
COB-ID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
客户端 | 600h+ nodeID | 40h | 索引 | 子索引 | ||||||
服务器 | 正常 | 580h+ nodeID | 43h | 索引 | 子索引 | 数据 | ||||
47h | 数据 | |||||||||
4bh | 数据 | |||||||||
4fh | 数据 | |||||||||
异常 | 80h | 错误代码 |
快速SDO的比较麻烦的就在于不好记CS(command specifier)命令,也就是SDO报文数据段的第一个字节的数据。这里我们结合下面这张图或许能更好的理解。
客户端发送快速SDO写请求时:
CCS(client command specifier)=1 ;
e(transfer type)始终为1,表示快速SDO;
s(size indicator),始终为1;如果指定数据长度,则为1,否则为0;
n(number of bytes invalid),只有s和n同时为1时才有效,否则为无效;发送快速SDO时n是有效的,表示can数据帧8个字节数据段长度的无效字节数;
x(not used);
CS(command specifier) | 说明 | CSC(client command specifier) | e(transfer type) | s(size indicator) | n |
---|---|---|---|---|---|
23h | 写4字节 | 1 | 1 | 1 | 0 |
27h | 写3字节 | 1 | 1 | 1 | 1 |
2bh | 写2字节 | 1 | 1 | 1 | 2 |
2fh | 写1字节 | 1 | 1 | 1 | 3 |
服务器回复快速SDO写请求正常:
SCS(server command specifier)写请求写入正常服务器回复0x60;
客户端发送快速SDO读请求时:
CCS(client command specifier)=2;
x(not used);
服务器回复快速SDO读请求正常:
SCS(server command specifier)= 2;
x(not used);
e(transfer type)始终为1,表示快速SDO;
s(size indicator),始终为1;如果指定数据长度,则为1,否则为0;
n(number of bytes invalid),只有s和n同时为1时才有效,否则为无效;发送快速SDO时n是有效的,表示can数据帧8个字节数据段长度的无效字节数。
4.3 普通SDO
当传输的数据超过四字节时,就不能使用快速SDO传输,必须使用普通SDO进行分帧传输,这种应用在实际中很少,至少目前我还没有用过。
a)客户端读取超过四字节数据对象时,起始帧和快速SDO读取数据帧内容相同;
b)服务器接收到SDO读命令后判断对象数据超过四字节后,回复数据帧中会把的CS字节中的e(transfer type)位置0表示普通SDO传输;s(size indicator)位仍为1,此时n(number of bytes invalid)区无效为0,数据段包含四个字节有效数据。
COB-ID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
客户端 | 600h+ nodeID | 40h | 索引 | 子索引 | - | - | - | - | ||
服务器 | 正常 | 580h+ nodeID | 41h | 索引 | 子索引 | 数据长度 | ||||
异常 | 80h | 终止代码 |
c)客户端接收到服务器应答后继续读取剩余数据,数据格式如下图所示;
COB-ID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
客户端 | 600h+ nodeID | 60h | - | - | - | - | - | - | - | |
服务器 | 正常 | 580h+ nodeID | 00h | 数据长度 | ||||||
异常 | 80h | 索引 | 子索引 | 终止代码 | ||||||
客户端 | 600h+ nodeID | 70h | - | - | - | - | - | - | - | |
服务器 | 正常 | 580h+ nodeID | 10h | 数据长度 | ||||||
异常 | 80h | 索引 | 子索引 | 终止代码 |
此时,CS(command specifier)有所改变。
ccs(client command specifier)位段为3;
t(toggle bit)位需要交互发送0和1,第一条数据帧t位置0,第二条置1,依次交互。服务器应答数据t位与请求帧保持一致,c位和n位段都是置0;
d)按照上述规律进行分段传输后,一直到最后一帧应答数据,服务器段会在其CS(command specifier)字节处加上末尾帧标志(c位被置1)和数据有效长度(8-n),其报文结构如下;
COB-ID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
客户端 | 600h+ nodeID | 60h/70h | 索引 | 子索引 | - | - | - | - | ||
服务器 | 正常 | 580h+ nodeID | 01h/11h | 数据长度 | ||||||
03h/13h | 数据长度 | - | ||||||||
05h/13h | 数据长度 | - | - | |||||||
07h/17h | 数据长度 | - | - | - | ||||||
09h/19h | 数据长度 | - | - | - | - | |||||
0bh/1bh | 数据长度 | - | - | - | - | - | ||||
0dh/1dh | 数据长度 | - | - | - | - | - | - | |||
异常 | 80h | 索引 | 子索引 | 终止代码 |
写超过四字节对象具体过程就不给大家展示了,比较繁琐而且使用普通SDO读写数据实用性也不太强,这里贴一张流程图,自己看看吧。
五、过程数据对象
PDO属于过程数据主要用来收发实时数据,即单向传输,无需接收节点回应CAN报文来确认。其数据类型、映射关系和传输方式由PDO通讯参数和映射参数共同决定。它的传输遵循的是生产者-消费者模型,即CAN总线网络中生产者产生的,TPDO可根据COB-ID由网络上一个或多个消费者RPDO接收,传输模型如下图所示。
5.1 PDO对象
按照接收和发送的不同,PDO可分为RPDO和TPDO。PDO由通信参数和映射参数共同决定最终传输的方式及内容。一般设备可能默认使用4个RPDO和4个TPDO来实现PDO的传输,对象列表如下。
名称 | COB-ID | 通信对象 | 映射对象 | |
RPDO(以节点自身为参考) | 1 | 200h+nodeID | 1400h | 1600h |
2 | 300h+nodeID | 1401h | 1601h | |
3 | 400h+nodeID | 1402h | 1602h | |
4 | 500h+nodeID | 1403h | 1603h | |
TPDO(以节点自身为参考) | 1 | 180h+nodeID | 1800h | 1A00h |
2 | 280h+nodeID | 1801h | 1A01h | |
3 | 380h+nodeID | 1802h | 1A02h | |
4 | 480h+nodeID | 1803h | 1A03h |
5.2 PDO通讯参数
PDO的通信参数,定义了该pdo使用的COB-ID,传输类型、定时周期等。其中RPDO通讯参数位于对象字典索引的1400h to 15FFh区间,TPDO通讯参数位于对象字典索引的1800h to 19FFh区间。每条索引代表一个PDO的通信参数集,其中的子索引分别指向具体的各种参数。
a)子索引0x0 :表示该索引中有几条子索引;
b)子索引0x01: COB-ID即这个PDO发出或者接收的对应CAN帧 ID,确定了该PDO的总线优先级(值得注意的是最高位valid确定该PDO是否有效,如果想禁用该条PDO可以把最高位置1);
c)子索引0x02:定义了该条PDO使用哪种传输方式;PDO的传输共有两种传输方式,分别为同步传输和事件传输。对于RPDO当传输类型为254或255时,会将接收到的数据立即更新到应用程序;当传输类型为0-240时,只有接收到下一个同步帧则才会将最新接收到的RPDO数据更新到应用程序。对于TPDO传输类型为1-240时,其同时也是TPDO的传输速率基于同步帧的倍频,当TPDO传输类型为0时,只有映射数据发生改变且收到一个同步帧才会发送。
通讯类型数值 | 同步 | 异步 | |
循环 | 非循环 | ||
0 | √ | ||
1-240 | √ | ||
241-253 | reserved | ||
254、255(event-driven) | √ |
d)子索引0x03:定义了禁止时间用于约束同一条PDO的发送间隔,避免总线被同一条优先级较高的PDO长时间占领。设置该数值后,同一个TPDO传输间隔时间不得小于该参数,该参数单位为100us。在该条PDO生效时(子索引0x01数据最高位被置0时)无法修改该参数。
e)子索引0x04:我看DS301里面没有规定,不说了。
f)子索引0x05:定义了事件计时器,单位为ms。值为0时表示禁止事件定时器。
g)子索引0x06:定义了同步帧起始值,这个只针对TPDO。
5.3 PDO映射参数
每个PDO数据长度最多可达8个字节,可同时映射一个或多个对象。PDO的映射参数就是指该条PDO(RPDO或TPDO)所包含的对象的个数及每个对象的索引、子索引及映射对象长度信息。
a)从上图可以看出子索引0记录PDO具体映射的对象个数,是有写权限的的。
b)子索引1-8的四字节数据段包含的是映射对象的索引、子索引及数据长度信息,如下图所示。
对象长度 | 位长 |
08h | 8位 |
10h | 16位 |
20h | 32位 |
c)PDO映射参数重映射流程如下:
①禁用该PDO,即先将通讯参数的子索引0x01的参数最高位置1;
②将映射参数的子索引0x00的参数清零;
③将映射参数的子索引0x1-0x8替换为新的对象;
④根据第三步已映射对象的个数,将其填入映射参数子索引0x00的参数中;
⑤将通讯参数的子索引0x01的参数最高位置0,使能该PDO;
六、同步对象
同步对象(SYNC)是控制多个节点发送与接收之间协调和同步的一种特殊机制,用于PDO的同步传输。同步对象的传输遵循生产者-消费者模型,由同步生产者发出同步帧,网络中其它节点作为消费者接收该同步帧。一般,同一个can网络中只允许有一个激活的同步生产者。与同步对象相关联的几个对象在通讯参数段,分别是0x1005-00、0x1006-00和0x1007-00。
a)object1005h:定义了同步对象的COB-ID,如下图所示。一般默认值为0x00000080,如果需要当前节点作为同步生产者,需要将gen(generate)位置1,表示由该节点发出同步帧信息。
b) object1006h:定义了同步循环周期,单位为us。其值必须大于0,否则不会产生同步帧。
c) object1007h:定义了同步窗口时间,单位为us。其值必须大于0,否则无效。同步窗口主要用于同步PDO,约束从节点发送PDO的时效。
七、紧急对象服务
当CANOPEN节点出现错误时,节点会发送一帧紧急报文。紧急报文遵循生产者-消费者模型,节点故障发出后,CAN网络中其它节点可选择处理该故障。
与紧急对象相关联的几个对象在通讯参数段,分别是0x1001-00、0x1003-00、0x1014-00、0x1015。
a)object1001h:各个位分别定义了节点的错信信息,can设备将内部发生错误时将错误信息映射到该对象。
b)object1003h:预定义错误场,功能在于保存历史错误信息。子索引0x0表示记录的实际错误数据,如果没有错误则值为0;只能对其写入非0值,写入0时将清除全部错误记录。从子索引0x01开始为记录所有错误信息,其32位数据区存储的信息包含16位错误码和16位的附加错误信息,如下图所示。
c)object1014h:定义紧急的COB-ID,一般默认值为0x80+nodeID,如果禁止产生紧急报文,可以将最高位置1。
d)object1015h:定义紧急报文禁止生产时间,单位100us。
八、通信协议对象
8.1 对象字典通信对象表
8.2 部分通信对象简述
上表中有些对象前面已经介绍过,这里就不再介绍了。还有一部分不太常用,我们挑一些稍微重要的介绍一下。
a)object1000h:存储设备类型;
b)object1008h:存储制造商设备名称;
c)object1009h:存储制造商硬件版本;
d)object100Ah:存储制造商软件版本;
e)object1012h:定义时间戳对象的COB-ID,结构如下图所示。其默认值为0x100;consume位定义设备是否使用时间戳消息,默认0不使用;produce位定义设备是否产生时间戳消息,默认0不产生。
f)object1013h:时间戳信息;
g)object1016h:该对象为期望的生产者心跳超时时间,这个值应该大于生产者的心跳周期;
h)object1200h-01:定义R-SDO的COB-ID,默认值600+nodeID;SDO仅在valid位在置0时有效。dyn位置1是用于动态SDO连接的canopen设备。
i)object1200-02h:定义T-SDO的COB-ID,默认值580+nodeID;