图 36 设置选定从站的RPDO的映射参数
(4) (5)
编译openCONFIGURATOR工程,然后运行例子,这些与Preq/Pres模式相同。 Wireshark 抓取POWERLINK 数据包,显示网络中没有了Preq cn2数据桢,因为2
号节点从主站的Pres MN 数据桢得到数据。
2.4 openCONFIGURATOR配置交叉通信
交叉通信,是指某个从站除了可以接收来自主站的数据,还可以接收来自其他从站的数据。例如2号从站除了可以接收来自主站的数据,还可以接收来自1号从站的数据以及3号从站的数据。经过配置,2号从站可以接收来自任何从站的数据。这称为交叉通信。 (1) 创建openCONFIGURATOR工程,Import 主站和从站的XDD文件。 (2) 配置接收和发送的网络参数和映射参数。
TPDO的配置:此处与Preq/Pres模式完全相同。
RPDO的配置: 如果该从站节点需要接收来自n号从站节点的数据,那么NodeId一栏的值设为n。例如,该从站节点需要接收来自主站的数据,并把接收到的数据存放到object 0x6200/01中;该从站节点需要接收来自1号节点的数据,并把接收到的数据存放到object 0x6200/02中;同时该从站节点需要接收来自3号节点的数据,并把接收到的数据存放到object 0x6200/03中,对于该种应用,由于这里的2号从节点需要接收来自主站的数据,也需要接收来自1号从站和3号从站的数据,因此2号从节点需要有3个RPDO通道来描述这个通信过程。在2号从节点的对象字典(objdict.h)中需要定义3个RPDO通道,假设分别为0x1400/0x1600, 0x1401/0x1601, 0x1402/0x1602。具体的定义如下: // Object 1400h: PDO_RxCommParam_00h_REC
EPL_OBD_BEGIN_INDEX_RAM(0x1400, 0x03, EplPdouCbObdAccess) EPL_OBD_SUBINDEX_RAM_VAR(0x1400, 0x00, kEplObdTypUInt8, kEplObdAccConst, tEplObdUnsigned8, NumberOfEntries, 0x02)
EPL_OBD_SUBINDEX_RAM_VAR(0x1400, 0x01, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NodeID_U8, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1400, 0x02, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, MappingVersion_U8, 0x00)
21
EPL_OBD_END_INDEX(0x1400)
// Object 1401h: PDO_RxCommParam_01h_REC
EPL_OBD_BEGIN_INDEX_RAM(0x1401, 0x03, EplPdouCbObdAccess) EPL_OBD_SUBINDEX_RAM_VAR(0x1401, 0x00, kEplObdTypUInt8, kEplObdAccConst, tEplObdUnsigned8, NumberOfEntries, 0x02)
EPL_OBD_SUBINDEX_RAM_VAR(0x1401, 0x01, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NodeID_U8, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1401, 0x02, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, MappingVersion_U8, 0x00) EPL_OBD_END_INDEX(0x1401)
// Object 1402h: PDO_RxCommParam_02h_REC
EPL_OBD_BEGIN_INDEX_RAM(0x1402, 0x03, EplPdouCbObdAccess) EPL_OBD_SUBINDEX_RAM_VAR(0x1402, 0x00, kEplObdTypUInt8, kEplObdAccConst, tEplObdUnsigned8, NumberOfEntries, 0x02)
EPL_OBD_SUBINDEX_RAM_VAR(0x1402, 0x01, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NodeID_U8, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1402, 0x02, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, MappingVersion_U8, 0x00) EPL_OBD_END_INDEX(0x1402)
// Object 1600h: PDO_RxMappParam_00h_AU64
EPL_OBD_BEGIN_INDEX_RAM(0x1600, 0x03, EplPdouCbObdAccess) EPL_OBD_SUBINDEX_RAM_VAR(0x1600, 0x00, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NumberOfEntries, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1600, 0x01, kEplObdTypUInt64, kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL)
EPL_OBD_SUBINDEX_RAM_VAR(0x1600, 0x02, kEplObdTypUInt64, kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL) EPL_OBD_END_INDEX(0x1600)
// Object 1601h: PDO_RxMappParam_01h_AU64
EPL_OBD_BEGIN_INDEX_RAM(0x1601, 0x03, EplPdouCbObdAccess)
22
EPL_OBD_SUBINDEX_RAM_VAR(0x1601, 0x00, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NumberOfEntries, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1601, 0x01, kEplObdTypUInt64, kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL)
EPL_OBD_SUBINDEX_RAM_VAR(0x1601, 0x02, kEplObdTypUInt64, kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL) EPL_OBD_END_INDEX(0x1601)
// Object 1602h: PDO_RxMappParam_02h_AU64
EPL_OBD_BEGIN_INDEX_RAM(0x1602, 0x02, EplPdouCbObdAccess) EPL_OBD_SUBINDEX_RAM_VAR(0x1602, 0x00, kEplObdTypUInt8, kEplObdAccRW, tEplObdUnsigned8, NumberOfEntries, 0x00)
EPL_OBD_SUBINDEX_RAM_VAR(0x1602, 0x01, kEplObdTypUInt64, kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL)
EPL_OBD_SUBINDEX_RAM_VAR(0x1602, 0x02, kEplObdTypUInt64,
kEplObdAccRW, tEplObdUnsigned64, ObjectMapping, 0x00LL) EPL_OBD_END_INDEX(0x1602)
由于接收到的数据保存到了0x6200/01,0x6200/02,0x6200/03里,因此需要在对象字典中定义如下object。
EPL_OBD_BEGIN_INDEX_RAM(0x6200, 0x04, NULL)
EPL_OBD_SUBINDEX_RAM_VAR(0x6200, 0x00, kEplObdTypUInt8, kEplObdAccConst, tEplObdUnsigned8, number_of_entries, 0x3)
EPL_OBD_SUBINDEX_RAM_USERDEF(0x6200, 0x01, kEplObdTypUInt8, kEplObdAccVPRW, tEplObdUnsigned8, Recvb1, 0x0)
EPL_OBD_SUBINDEX_RAM_USERDEF(0x6200, 0x02, kEplObdTypUInt8,
kEplObdAccVPRW, tEplObdUnsigned8, Recvb1, 0x0)
EPL_OBD_SUBINDEX_RAM_USERDEF(0x6200, 0x03, kEplObdTypUInt8,
kEplObdAccVPRW, tEplObdUnsigned8, Recvb1, 0x0) EPL_OBD_END_INDEX(0x6200)
同样,XDD文件修改如下图 37所示:
23
图 37 XDD文件中的object
XDD文件中关于0x6200的描述, 如下图 38所示。:
图 38 XDD文件中索引为0x6200的object
接下来创建新的openCONFIGURATOR工程,对2号从节点的配置, 如下图 39所示:
图 39 设置选定节点的RPDO的通信参数
这里需要说明如下几点:
24
(1) 为什么我们修改了“No 0”的“Node Id”, “No 1”的“Node Id”也跟着变?
原因是节点2 有3个RPDO通道,第一个RPDO通道有0x1600/01, 0x1600/02两个映射,这两个映射对应着“No 0”和“No 1”。一个RPDO通道只能用于描述来自一个节点的数据,“No 0”和“No 1”属于一个RPDO通道,因此他们的“Node Id”会保持一致。
(2) “offset”:这个参数是指从接收到的数据包的哪个位置开始取数据,因来自主站,
1号节点和3号节点的数据,是3个独立的数据包。在取数据的时候,都是从数据包的开始位置取,因此“offset”都为“0x0000”。
(3) 这里省略了对主站发送给2号从站的TPDO的配置,以及1号从节点和3号从节点的
TPDO的配置。
完成上述配置后,接下来运行该例程:
(1) 编译工程,将生成的.CDC文件和xap.h文件复制到主站工程目录下。 (2) 程序运行。我们需要有3台
PC, 一台作为主站,运行
Examples\\X86\\Windows\\VC8\\demo_cfm_pcap下的例子,另外两个运行Examples\\X86\\Windows\\VC9\\demo_pcap下的例子,将节点号一个设置为2,另一个设置为3。
(3) 对于2号从节点的程序修改如下:
定义3个变量,分别和0x6200/01,0x6200/02,0x6200/03这三个object 链接,并在同步回调函数中打印。
ObdSize = sizeof(bVarOut1_l); uiVarEntries = 1;
EplRet = EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize, 0x01); if (EplRet != kEplSuccessful) {
goto ExitShutdown; } EplRet = EplApiLinkObject(0x6200, &bVarOut1_2, &uiVarEntries, &ObdSize, 0x02); if (EplRet != kEplSuccessful) {
goto ExitShutdown; } EplRet = EplApiLinkObject(0x6200, &bVarOut1_3, &uiVarEntries, &ObdSize, 0x03); if (EplRet != kEplSuccessful) {
goto ExitShutdown;
}
同步回调函数修改如下:
25