第二部分、CANopen协议:
第五节、关于COB-ID:
CANopen是在基础CAN协议的基础上,仅仅对应用层做了约定而来。
CANopen里的通信对象ID叫COB-ID,仍然利用了标准帧的11位ID,只是约定高4位(7~10位)为功能码;低7位(0~6位)为节点ID(支持最多127个节点)。
功能码和节点ID组合的结果,如下图所示
第二列是功能码,第三列就是功能码和节点ID组合的结果。第三列注意的是,蓝色部分的节点ID都是从1开始。以PDO1(tx)为例,功能码0011,加上第一个节点ID:000,0001(切记,不能从0开始),组合后就是001,1000,0001,也就是16进制的181或者10进制的385。同理,PDO1(tx)最大值是0x1FF。
上图绿色部分是广播的通讯对象,蓝色部分是点对点通讯对象。并且,从上往下优先级依次降低(由仲裁机制实现),比如SDO的优先级就比PDO低。
第六节、关于PDO:
PDO分tx和rx两种,分别叫TPDO和RPDO。TPDO由生产者提供,不需要应答。每个节点最多只能支持4对TPDO/RPDO。以节点1为例,TPDO的COB-ID分别是0x181、0x281、0x381和0x481;RPDO的COB-ID分别是0x201、0x301、0x401、0x501。
每个TPDO或RPDO,都各自需要两套参数,分别叫通讯参数和映射参数:其中通讯参数用来设置各种总线参数,比如使用哪个COB-ID,传输类型,禁用时间和定时时间等;映射参数用来组成(TPDO)或解析(RPDO)报文中的数据域部分。所有这些参数,都放在对象字典中,收发双发拿着同一份字典,就能彼此识别对方的报文内容了。
第七节、关于对象字典:
对象字典是一个大杂烩,里面存储着收发各方共同的通信约定。有了这份字典,总线上的各个节点,就能组织发送报文或者解析接收报文了。对象字典名字里的对象,应该是从面向对象引申来的概念,指有一定数据结构的变量。所以对象字典,理解成变量字典也行。
对象字典的内容分配大致如下表所示,全球统一,但具体细节可以自由发挥。下图左侧的索引,是字典条目的索引号,和COB-ID没有任何关系。并且对象字典的索引实际上分为16位的主索引和8位的子索引,下表只列出了主索引。
上表中的0x1000~0x1FFF索引区,又可以细分为如下表所示的子区域。
第一行的0x1000~0x1029区域,属于已经约定好的区域,定义如下面两张图:
重点关注0x1400~0x1BFF区域,即PDO的参数对象区。
如前所述,一个节点支持4对TPDO/RPDO,每个PDO都有两套参数(通讯参数和映射参数),每套参数(不是每个参数)占用一个主索引号。所以一个节点就要占用16个主索引号来存放参数,128个节点就要占用2048个(0x800)主索引号,索引号在字典中的编号从0x1400开始,到0x1BFF结束。
实际上在字典中,通信参数放一块,映射参数放一块,分布如下图所示:
上图是PDO参数的主索引分布。但实际上的参数是成套出现的,一套参数里包含若干子参数,子参数要靠子索引来查询。下图是通信参数子索引定义:
下图是映射参数子索引定义:
映射参数最多可以映射64个对象(数据结构变量),子索引从0x01到0x40。
下图是一个具体的根据映射参数构成TPDO的例子(节点1的TPDO1):
首先生产者从[1800,01](逗号前表示主索引,逗号后表示子索引,后同)中得到COB-ID。然后从[1A00,01]中获取第一个对象。[1A00,01]中的值为0x20000108,那么第一个对象为[2000,01],对应值为A,在PDO中占0x8位。接着是第二个对象[2003,03],对应值为G,在PDO中占0x10位(16位)。最后是对象[2003,01],对应值E,在PDO中占0x8位。这样A、G、E(顺序不能颠倒)就组成了一个32位的TPDO的数据域了。
(补充建议,本篇是重中之重,对象字典的部分反复阅读三遍是起码的,阅读五六遍才能理解也不奇怪,坚持!)