CANopen Master Documentation
Version 6.06.02
Loading...
Searching...
No Matches
PDO communication

The CANopen Master protocol stack provides two solutions for PDO handling: PDO Mapping and PDO Queue. The solutions are depicted in the figure PDO handling. Both solutions can be used independent from each other.

Configuration of a RPDO or TPDO is done via the ComPdoConfig() function. Please note that the function disables the transmission of TPDOs and reception of RPDOs as default. A PDO has to be enabled by calling ComPdoEnable() by the application program. The following code snipped provides an example for an enabled RPDO1:

//----------------------------------------------------------------------------------
// add first receive PDO, ID = 0x201, enable reception
//
@ eCOM_NET_1
Definition com_defs.h:746
@ ePDO_DIR_RCV
Definition com_pdo.h:91
@ ePDO_TYPE_EVENT_PROFILE
Definition com_pdo.h:177
ComStatus_tv ComPdoConfig(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubPdoDirV, uint32_t ulIdV, uint8_t ubDlcV, uint8_t ubTypeV, uint16_t uwTimeV)
ComStatus_tv ComPdoEnable(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubPdoDirV, uint8_t ubEnableV)

PDO Mapping

PDO mapping allows automatic distribution of values received by a RPDO to the corresponding entries of the object dictionary. In the same way values stored in the object dictionary can be copied into a TPDO, as shown in the next figure.

If PDO mapping is used, the possible mapping entries (i.e. data elements of the object dictionary which can be mapped into a PDO) are defined in different *.inc files. The file com_mobj_rpdo.inc contains a list with possible mapping entries for RPDOs, the file com_mobj_tpdo.inc contains a list with possible mapping entries for TPDOs. In addition to the mapping entries, optional callback handlers can be added as an option. For a RPDO the handler is called after PDO reception, for a TPDO the handler is called before PDO transmission.

On reception of a RPDO data will be distributed to all mapped values defined by structure ComPdoMapping_s::pvdData before the optional handler (ComPdoMapping_s::pfnHandler) is called. On transmission of a TPDO the data will be collected from all mapped values defined by ComPdoMapping_s::pvdData after the optional handler (omPdoMapping_s::pfnHandlerpfnHandler) has been called.

RPDO mapping example

The function ComPdoRcvMapAdd() is used to map entries to the desired position inside the RPDO. The RPDO mapping example from the figure above would require the following file contents of com_mobj_rpdo.inc:

//----------------------------------------------------------------------------------
// com_mobj_rpdo.inc
{
//--------------------------------------------------------------------------
// 2000:00h, 8 bit size, variable ubComMob_ObjectA
//
.ulMapEntry = 0x20000108, // mapping entry
.pvdData = &ubComMob_ObjectA, // pointer to variable
.pfnHandler = ComMob_PdoRcvHandler // optional handler
},
{
//--------------------------------------------------------------------------
// 2000:02h, 16 bit size, variable uwComMob_ObjectB
//
.ulMapEntry = 0x20000210, // mapping entry
.pvdData = &uwComMob_ObjectB, // pointer to variable
.pfnHandler = ComMob_PdoRcvHandler // optional handler
},
{
//--------------------------------------------------------------------------
// 2000:03h, 8 bit size, variable ubComMob_ObjectC
//
.ulMapEntry = 0x20000308, // mapping entry
.pvdData = &ubComMob_ObjectC, // pointer to variable
.pfnHandler = ComMob_PdoRcvHandler // optional handler
},

In the application, the RPDO is configured in the following manner:

void MySetupRPDO(void)
{
ComPdoRcvMapEnable(eCOM_NET_1, 0, 0); // delete existing mapping, if present
ComPdoRcvMapAdd( eCOM_NET_1, 0, 0, 0x20000308); // map object C, 2000:03h
ComPdoRcvMapAdd( eCOM_NET_1, 0, 1, 0x20000210); // map object B, 2000:02h
ComPdoRcvMapAdd( eCOM_NET_1, 0, 2, 0x20000108); // map object A, 2000:01h
ComPdoRcvMapEnable(eCOM_NET_1, 0, 3); // enable 3 mapping entries
}
ComSdoStatus_tv ComPdoRcvMapEnable(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubMapNumberV)
ComSdoStatus_tv ComPdoRcvMapAdd(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubMapIdxV, uint32_t ulMapEntryV)

TPDO mapping example

The function ComPdoTrmMapAdd() is used to map entries to the desired position inside the TPDO. The TPDO mapping example from the figure above would require the following file contents of com_mobj_tpdo.inc:

//----------------------------------------------------------------------------------
// com_mobj_tpdo.inc
{
//--------------------------------------------------------------------------
// 2001:00h, 8 bit size, variable ubComMob_ObjectD
//
.ulMapEntry = 0x20010008, // mapping entry
.pvdData = &ubComMob_ObjectD, // pointer to variable
.pfnHandler = ComMob_PdoTrmHandler // optional handler
},
{
//--------------------------------------------------------------------------
// 2002:00h, 16 bit size, variable ubComMob_ObjectE
//
.ulMapEntry = 0x20020010, // mapping entry
.pvdData = &uwComMob_ObjectE, // pointer to variable
.pfnHandler = 0L // optional handler
},
{
//--------------------------------------------------------------------------
// 2003:00h, 32 bit size, variable ubComMob_ObjectF
//
.ulMapEntry = 0x20030020, // mapping entry
.pvdData = &ubComMob_ObjectF, // pointer to variable
.pfnHandler = 0L // optional handler
},

In the application, the TPDO is configured in the following manner:

void MySetupTPDO(void)
{
ComPdoTrmMapEnable(eCOM_NET_1, 0, 0); // delete existing mapping, if present
ComPdoTrmMapAdd( eCOM_NET_1, 0, 0, 0x20010008); // map object D, 2001:00h
ComPdoTrmMapAdd( eCOM_NET_1, 0, 1, 0x20030020); // map object F, 2003:00h
ComPdoTrmMapEnable(eCOM_NET_1, 0, 2); // enable 2 mapping entries
}
ComSdoStatus_tv ComPdoTrmMapAdd(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubMapIdxV, uint32_t ulMapEntryV)
ComSdoStatus_tv ComPdoTrmMapEnable(uint8_t ubNetV, uint16_t uwPdoNumV, uint8_t ubMapNumberV)

RPDO Queue

On reception of configured RPDOs the complete CAN message can optionally be stored into a receive queue. The RPDO queue is disabled by default.

void MyReadRPDO(void)
{
uint16_t uwNumberOfMessagesT;
CpCanMsg_ts tsCanMsgT;
ComPdoRcvQueueEnable(eCOM_NET_1); // enable RPDO queue
ComPdoRcvQueueCount(eCOM_NET_1, &uwNumberOfMessagesT); // get number of messages in RPDO queue
while (uwNumberOfMessagesT > 0)
{
// .. do something with CAN message
ComPdoRcvQueueCount(eCOM_NET_1, &uwNumberOfMessagesT);
}
}
ComStatus_tv ComPdoRcvQueueCount(uint8_t ubNetV, uint16_t *puwCountV)
ComStatus_tv ComPdoRcvQueueFetch(uint8_t ubNetV, CpCanMsg_ts *ptsCanMsgV)
ComStatus_tv ComPdoRcvQueueEnable(uint8_t ubNetV)
CAN message structure.
Definition canpie.h:1005

In the same way it is possible to send configured TPDOs via the command ComPdoTrmPacket().