...
There is a template (template/main.c) for coding the main routine. It is recommended to use this template for rapid programming. The following steps are necessary for the design of an application:·
design of the boot-up behavior (initialization)
...
design of the application
...
design of the shutdown behavior
The boot-up behavior of an application requires the following:·
hardware initialization: iniDevice()
...
initialization of CAN controller, timer and ISR’s: initCan()
...
initialization of the CANopen Library: init_Library()
This function is generated by the Industrial Communication Creator. The initialization is saved in file co_init.c.·
modify communication parameter at the object dictionary if necessary
...
initialize application
...
activation of interrupts for CAN and timer
...
starting of all nodes startRemoteNodeReq() (only master)
The difference between a NMT master and a NMT slave is that the NMT master controls all network participants. Therefore each NMT master application has to manage the network. In the CANopen Library the NMT master collects all communication relevant information in a node management list (network). With this list the NMT master is able to guard the nodes and to influence their communication states. Before all network participants changes into the state NMT/OPERATIONAL the NMT master or another configuration application can parameterize their communication variables i.e. COB-ID, PDO mapping.
Code Block | ||
---|---|---|
| ||
int main(void) |
...
{
{ RET_T coRetVal; /* CANopen Library return value */ |
...
UNSIGNED8 ret; /* return value for common purpose */ |
...
BOOL_T err = CO_FALSE; /* error flag */ |
...
/* initialization of hardware */ |
...
ret = iniDevice(); |
...
...
/* initialize CAN controller with CAN bit rate of 125 kbit/s */ |
...
ret = initCan(125); |
...
/* initialize CANopen Library and execute CANopen minimum boot-up */ |
...
coRetVal = init_Library(); |
...
/* initialize CANopen timer */ |
...
initTimer(); |
...
/* start CAN controller */ |
...
Start_CAN(); |
...
...
/* enable interrupts */ |
...
ENABLE_CPU_INTERRUPTS(); |
...
} |
Listing 35: example for initialization
The design of the application is the user’s task. He has to ensure that the CAN message buffer is read continously or event driven. The easiest way to perform this is an endless loop from which the buffer read function and the application functions are called cyclically, see Listing 36.
Code Block | ||
---|---|---|
| ||
int main(void) |
...
{ |
...
. . . |
...
/* main loop */ |
...
while(1) |
...
{ |
...
/* manage received CAN messages and |
...
time-dependent CANopen services */ |
...
FlushMbox(); |
...
/* application function */ |
...
application(); |
...
} |
...
} |
Listing 36: endless loop reception process
But it is also possible to call FlushMbox() by a Real Time Operating System signal or other mechanisms. Then the user’s application runs within other tasks, see Listing 37.
Code Block | ||
---|---|---|
| ||
while(1) |
...
{ |
...
/* sleep while no CAN event |
...
CANopen task should be woken up: |
...
- if a new message is received
- if the CANopen timer is expired
in order to check all CANopen timers */
...
- if a new message is received - if the CANopen timer is expired in order to check all CANopen timers */ os_wait(event); |
...
/* interpret received message or handle CANopen timers */ |
...
FlushMbox(); |
...
} |
Listing 37: signal-driven process
...
stop all nodes stopRemoteNodeReq() (only master)
deactivate the ISRs for CAN and timer
de-initialize CAN controller, timer and their ISR’s
delete the node entries removeRemoteNodeReq() (only master)
delete the local node deleteNodeReq()
delete the node management list (network) deleteNetworkReq() (only master)
de-initialize the CANopen Library leaveCANopen()
Code Block | ||
---|---|---|
| ||
main() |
...
{ |
...
.... |
...
/* release all resources */ |
...
releaseTimer(); |
...
deleteNodeReq(); |
...
/* leave CANopen */ |
...
leaveCANopen(); |
...
return(0); |
...
} |
Listing 38: example for shutdown
...