...
The NMT master administers the communication states of all nodes in the network. Therefore the NMT master must create appropriate administrative structures with the function createNetworkReq(). Each node in the network where the NMT master will send NMT commands to has to be registered using the function addRemoteNodeReq(), see Listing 21.
Code Block | ||
---|---|---|
| ||
/* create a network structure for using Heartbeat */ |
...
createNetworkReq(CO_LINE_PARA); |
...
/* add remote node 12 with a Heartbeat consumer time of 500 ms */ |
...
addRemoteNodeReq(12, 500, 0, CO_TRUE, CO_FALSE CO_COMMA_LINE_PARA); |
...
/* add remote node 42 with a Heartbeat consumer time of 800 ms */ |
...
addRemoteNodeReq(42, 800, 0, CO_TRUE, CO_FALSE CO_COMMA_LINE_PARA); |
Listing 21: example for adding remote nodes to the NMT masters network
...
NMT commands can be transmitted either for individual nodes or for the entire network. The functions startRemoteNodeReq(), enterPreOpStateReq(), stopRemoteNodeReq(), resetCommReq() and resetNodeReq() are available for this task. Node-ID 0 is used to address all CANopen nodes.
Code Block | ||
---|---|---|
| ||
/* change all nodes in the network into the state NMT/OPERATIONAL */ |
...
startRemoteNodeReq(0 CO_COMMA_LINE_PARA); |
...
/* change node 7 into the state NMT/STOPPED */ |
...
stopRemoteNodeReq(7); |
...
/* change node 8 into the state NMT/PRE-OPERATIONAL */ |
...
enterPreOpStateReq(8); |
Listing 22: examples for initiation of NMT state transitions
...
The functionality for the CANopen LEDs can be activated with the Industrial Communication Creator.
Code Block | ||
---|---|---|
| ||
void ledInd ( |
...
UNSIGNED8 led, /**< [in] kind of CANopen LED */ |
...
UNSIGNED8 action /**< [in] desired LED state: on/off */ |
...
) |
...
{ |
...
if (CO_ERR_LED == led) |
...
{ |
...
if (CO_LED_ON == action) |
...
{ |
...
/* switch ERR LED on via CPU port 2, pin 3 */ |
...
P2.3 = 1; |
...
} |
...
else |
...
{ |
...
/* switch ERR LED off via CPU port 2, pin 3 */ |
...
P2.3 = 0; |
...
} |
...
} |
...
if (CO_RUN_LED == led) |
...
{ |
...
if (CO_LED_ON == action) |
...
{ |
...
/* switch RUN LED on via CPU port 2, pin 4 */ |
...
P2.4 = 1; |
...
} |
...
else |
...
{ |
...
/* switch RUN LED off via CPU port 2, pin 4 */ |
...
P2.4 = 0; |
...
} |
...
} |
...
} |
Listing 23: example for ledInd()
...
Table 31: overview of NMT startup request and indication functions
Code Block | ||
---|---|---|
| ||
/****************************************************************/ |
...
/* nmtStartupMasterInd - indicate a new master state |
...
This function is called if the master has reached a new state |
...
in the NMT startup process. |
...
* |
...
If the self-starting bit at index 0x1F80 is set then the NMT |
...
master changes into the state NMT/OPERATIONAL automatically. |
...
Afterwards this function is called with the parameter |
...
NMT_MASTER_IS_STARTED. |
...
* |
...
If the self-starting bit at index 0x1F80 is NOT set |
...
then the NMT master does not change into the state NMT/OPERATIONAL |
...
automatically. |
...
In this case this function is called with the parameter |
...
NMT_MASTER_READY4START |
...
and the startup process is waiting until the function |
...
nmtStartupContReq(0, NMT_CONT_START_MASTER) |
...
was called. |
...
* |
...
Parameter: |
...
NMT_MASTER_READY4START |
...
master is ready to go into OPERATIONAL |
...
NMT_MASTER_IS_STARTED |
...
master has been changed into OPERATIONAL |
...
* |
...
\return |
...
nothing |
...
*/ |
...
void nmtStartupMasterInd( |
...
UNSIGNED8 eventCode /**< [in] code for triggering event */ |
...
CO_COMMA_LINE_PARA_DECL /**< [in] additional parameter */ |
...
) |
...
{ |
...
switch (eventCode) |
...
{ |
...
/* NMT master is started automatically: |
...
bit 2 of object 0x1F80 is 0.
The NMT master has changed into the state OPERATIONAL by
itself. Application-specific actions can be done. */
...
bit 2 of object 0x1F80 is 0. The NMT master has changed into the state OPERATIONAL by itself. Application-specific actions can be done. */ case NMT_MASTER_IS_STARTED: |
...
PRINTF("self started0); |
...
break; |
...
case NMT_MASTER_READY4START: |
...
PRINTF("wait for master start0); |
...
/* application-specific actions */ |
...
/* wake up NMT Startup Manager */ |
...
nmtStartupContReq(0, NMT_CONT_START_MASTER); |
...
break; |
...
} |
...
} |
Listing 24: example for nmtStartupMasterInd()
...
Access to remote nodes is carried out with SDO read- and write accesses. The application has to provide the necessary service data objects in the object directory and needs to configure them.
Code Block | ||
---|---|---|
| ||
UNSIGNED8 rNodeId = 32; |
...
/* set cob-ids for sdo usage for sdo 1 */ |
...
setCobId(0x1280, 1, 0x600 + rNodeId); |
...
setCobId(0x1280, 2, 0x580 + rNodeId); |
...
/* check and update configuration of node 32 */ handleRemoteNodeConfig(rNodeId, 1); |
Conversion to concise DCF
The function convertToConciseDcf() provides the facility to convert standard DCF files to the concise format. To ensure the required configuration sequences for the various objects (like changing PDO mapping) the function has to be called repeatedly with different arguments. On each call the complete DCF is scanned and the needed objects are determined.
Code Block | ||
---|---|---|
| ||
/* pointer to Concise DCF Buffer */ |
...
UNSIGNED8 conDcfBuf[CONDCF_LEN]; |
...
/* max len of Concise DCF Buffer */ |
...
UNSIGNED32 conDcfLen = CONDCF_LEN; |
...
/* offset at DCF buffer */ |
...
UNSIGNED32 offs = 0; |
...
/* pointer to DCF Buffer */ |
...
UNSIGNED8 dcfBuf[DCF_LEN]; |
...
/* len of DCF Buffer */ |
...
UNSIGNED32 dcfLen = DCF_LEN; |
...
/* fill DCF Buffer and set length */ |
...
/* step 1 - convert standard objects to concise dcf */ convertToConsiveDcf(conDcfBuf, &conDcfLen, &offs, dcfBuf, dcfLen, \ |
...
DCF_CONVERT); |
...
/* step 2 - update mapping entries */ convertToConsiveDcf(conDcfBuf, \ |
...
&conDcfLen, &offs, dcfBuf, dcfLen, DCF_MAPPING); |
...
/* step 3 - setup COB-IDs for PDOs */ |
...
convertToConsiveDcf(conDcfBuf, &conDcfLen, &offs, dcfBuf, dcfLen, \ |
...
DCF_PDOCOB); |
Listing 25: concise DCF conversion
...
The object-specific callback must have the following function prototype:
Code Block | ||
---|---|---|
| ||
RET_T foo |
...
( |
...
UNSIGNED16 index, /**< [in] object index */ |
...
UNSIGNED8 subIndex, /**< [in] object sub-index */ |
...
CO_OBJ_CB_TYPE_T reason /**< [in] trigger parameters for callback */ |
...
CO_COMMA_LINE_PARA_DECL /**< [in] additional parameter */ |
...
); |
Listing 26: function prototype for object-specific callback
...
The parameter reason gives information to the trigger conditions for the call of the object-specific callback. The structure CO_OBJ_CB_TYPE_T summarizes the following trigger conditions:
Code Block |
---|
typedef struct { |
...
UNSIGNED16 reason; /**< kind of CANopen service with sample point */ |
...
UNSIGNED16 serviceNbr; /**< number of CANopen service */ |
...
} CO_OBJ_CB_TYPE_T; |
Listing 27: structure CO_OBJ_CB_TYPE_T
...
If the application needs to set or reset an object callback at run-time the function setObjFuncPtr() can be used. The prototype of the function is:
Code Block | ||
---|---|---|
| ||
RET_T setObjFuncPtr(UNSIGNED16 index, CO_OBJ_CB_T pNewFunc \ |
...
CO_COMMA_LINE_PARA_DECL); |
If the application wants to disable this callback, the new function pointer shall be set to NULL.
...