CAPL Used With CANoe And CANalyzer

Tips and Tricks for the Use of CAPL

CAPL is a procedural programming language similar to C, which was developed by Vector Informatik. The execution of program blocks is controlled by events. CAPL programs are developed and compiled in a dedicated browser. This makes it possible to access all of the objects contained in the database (messages, signals, environment variables) as well as system variables. In addition, CAPL provides many predefined functions to support users.

CAPL is supported by some Vector software tools − but on this website the focus is on its use with the tools CANoe and CANalyzer.

First we focus on the basics of CAPL. It is primarily intended for those who are new to this language; however, it also offers insights for well-informed users into the motivation behind individual CAPL constructs. Then we will discuss advanced functionalities of CAPL. Last but not least we will address performance and memory needs and offers tips and tricks on using databases and associative arrays.


Learn more about CAPL

... also check out our short video or the comprehensive webinar recording.


For over 20 years – it was initially used in CANalyzer for DOS – CAPL has been used to implement a broad bandwidth of tasks: from simple stimuli to the simulation of complex bus nodes. In the following, CANoe is illustratively named for the two products CANoe and CANalyzer. The goal of CAPL has always been to solve specific tasks as simply as possible. Typical tasks are reacting to received messages, checking and setting signal values and sending messages. A program should restrict itself to precisely these things and not require any additional overhead.

Many programming tasks that CANoe users typically perform might actually be as brief and trivial as the example presented below – of course many other tasks are not so trivial. That is why CAPL has been continually extended over the years to be a tool that can also solve complex tasks according to the principle “as simple as possible”.

“CAPL” is an acronym for Communication Access Programming Language. The original focus on CAN has long been extended to all automotive bus systems such as LIN, FlexRay, MOST, J1587, as well as a few others like ARINC and CANopen.

As in many other languages, the syntax of CAPL is closely based on the syntax of the C language. Those who are familiar with C, C#, or various modern script languages will quickly be quite comfortable using CAPL. However, a few unique aspects distinguish a CAPL program from a C program:

  • CAPL programs are event-driven. This means that they consist of individual functions, each of which reacts to an event within the system under analysis: receipt of a message, change of a signal, expiration of a timer, or even a change in the environment. To react to the message EngineState, for example, you would use On message EngineState (Figure 1 below).
  • CAPL programs use specific databases for the concepts of the system under analysis. Messages and signals get their names there, and these names can be used directly in the program code. In Figure 1 (see below), they are the names EngineState for a message and EngineSpeed for a signal in this message.
  • CAPL programs do not give the user any pointer types to use. Right from the outset this excludes numerous potential programming errors and causes of program crashes, such as those that frequently happen in C programming. Nonetheless, since pointers − aside from their susceptibility to errors − also represent a very powerful concept, CAPL provides a substitute for some things, e.g. associative arrays as a substitute for dynamic memory.

One important property that CAPL shares with C should be mentioned: CAPL is always compiled, i.e. it is converted to efficiently executable and flexible machine code.


CAPL Basics

3 Examples of CAPL programming in CANoe and CANalyzer (3:30 min)


Introduction to CAPL

... for CANoe and CANalyzer (60 min.)


A Simple CAPL Program

Figure 1: A simple example of a CAPL program
Figure 1: A simple example of a CAPL program

In this figure a simple CAPL program is presented, which performs one of the basic tasks of a bus monitoring tool: it listens to traffic on the bus and prepares a couple of events on the bus for observation/monitoring by the user. This is a shortened, sample CANoe program: “Display.can” from the sample “Easy.cfg”. In the following, first the overall functionality is briefly summarized, and then the individual sections are described in more detail.

Task Description

  • The task is to observe a CAN network whose elements – e.g. bus nodes, messages and transported signals – are described in a database.
  • When the EngineState message is received, then the EngineSpeed signal it contains is conditioned for display on a display panel, and it is routed to the panel.
  • When the LightState message is received, the HeadLight and FlashLight signals it contains are conditioned for display on a panel, and they are routed to the panel for graphic display.

Close Look at the Program

The line numbers in figure 1 are not part of the CAPL program and are only inserted here to make it easier to reference individual lines or sections. To achieve the most compact representation possible, opening brackets were not placed on a separate line.

In a CAPL program, it is possible to define global variables and constants. This is done in the variables section (lines 1 to 5). These constants and variables are globally defined for this program: they can be used anywhere in the program, but not in other programs within the same CANoe application. The other sections define reactions to events (lines 7 to 17) and an auxiliary function (lines 19 to 28).

Lines 7 to 9 show a minimal form of a message event procedure. This function is called whenever this message has been transmitted on the bus. In reference to CAN, this means that the precise time point is the TX or RX interrupt of the CAN controller, i.e. immediately after correct transmission of the message. The message that triggers the call of the particular function is referenced by this syntax.

In line 8, the value of the EngineSpeed signal is read out from the received message this and is assigned to a system variable with a conversion /1000.0.

Lines 11 to 17 show a message event procedure for the LightState message, which transmits the information for a turn signal flasher. Its processing is similar to that of the EngineState message with the following unique aspects: In line 12, the direction flag .dir is now checked in the message this that has been just transmitted. Only received messages should be considered in this program (value RX), because a message sent by the node itself would also trigger an event procedure (value TX). In this case, an error message would be output in line 15.

Since conditioning of the signal for display on the user interface (a panel on which different states are shown by different bitmaps) is somewhat more complex, its implementation is outsourced to a separate function: In line 13, SetLightDsp is called with the two message signals that are needed as parameters.

Finally, lines 19 to 28 define a separate function, which writes different values to the system variable LightDisplay in the Lights name space according to the value of the transmitted signal. In this demo configuration, this variable then selects the appropriate bitmap on a display panel.

Execution Model

A key difference between CAPL and C or C++ relates to when and how program elements are called. In C, for example, all processing sequences begin with the central start function main(). In CAPL, on the other hand, a program contains an entire assortment of procedures of equal standing, each of which reacts to external events:

  • Triggered by the system: These events include those that are useful for initializing and post-processing the measurement run: on preStart, on start, on preStop and on stopMeasurement, as well as the time control and keyboard events on timer and on key.
  • Triggered by bus communication: There are many different types of event procedures that react to bus events such as those related to communication or error handling, and they are very dependent on the bus type. Examples of these are on message and on busOff in CAN and on frFrame and on frStartCycle in FlexRay.
  • Triggered by access to a Value Object:  Such objects include system and environment variables that are globally available in CANoe and CANalyzer as well as signal values that represent a data interpretation of the bus communication. Special databases perform the interpretation. The sections further back will address this concept.


Event procedures are atomic: The simulation model of CANoe is event oriented. In event procedures, CANoe executes all actions simultaneously from the model perspective, namely at the point of in time of the triggering event. The actual computation time on a real PC is ignored.

Simulation time and time stamp: However, a real event generated by the PC, such as a bus output by output(), gets a time stamp of the real-time clock. The sequence and time points of these events can be influenced by bus protocols, driver, and hardware properties. On a simulated bus, some of the mentioned influencing parameters are eliminated. In this case, bus events are initiated simultaneously; in the case of CAN, for example, this leads to a dependable arbitration of multiple messages that are output by output().

Updating system variables: Users can also use CAPL to modify environment or system variables that are visible outside of the program. CAPL does not propagate value changes to a variable until after the current event processing is finished, but with the same time of the just handled event. A read access within the current procedure always returns the old value even if the variable appears to be set to a new value within the same procedure. The advantage is that only one value change occurs at a single point in time.

The execution model is situation dependent: There are many ways to use CAPL in CANoe and CANalyzer, and so the execution model varies somewhat, too: The simulation nodes of a CANoe simulation are in parallel on the bus. Hence, they are completely independent from each other. Triggered events are always dispatched to all programs. In contrast, nodes in the measurement setup and in CANalyzer are processed in sequential order: Each node passes its output to the next. Incoming events must be passed to the next node explicitly for further processing. The procedures on * and on [*] are provided for this purpose.

Another type of program is a test program whose test procedures can wait for external events. CAPL resumes execution with the simulation time of such events. In contrast, waiting in normal event procedures stalls the entire simulation system. This is a frequent source of errors when CAPL is used. It is therefore inadvisable to use a busy-wait or wait command in an external DLL.

Efficient Programming in CAPL

The preprocessor is a powerful tool in the C language, but it can also lead to confusion and consequently to errors. Therefore, only a subset of the well-known preprocessor directives in C is offered in CAPL with comparable semantics.

#include: Include files contain arbitrary but complete sections of a CAPL program: includes, variables and procedures. In contrast to C, the text of an include file is not simply inserted into the CAPL file, rather the sections. All sections of the included file apply to the entire parent CAPL file "as if" they were contained in that file. The sequence of sections is irrelevant in CAPL anyways. This means the compiler reports any duplicate symbols as an error. Moreover, code and data from included and parent files may use each other mutually. One exception to the just stated prohibition of duplicate symbols is that on start, on preStart, on preStop and on stopMeasurement may coexist in both the included file and the parent file. In these functions, the code is executed sequentially: first the code from the included file and then the code from the parent file. This means that the Include files are used to perform three tasks: declare data types, define variables and provide an (inline) function library.

#pragma library: CAPL programs can use Windows DLLs created in other languages, as long as they implement a suitable CAPL DLL interface. These DLLs can be directly linked with the directive #pragma library("capldll.dll").

Macros: In CAPL, there are a number of predefined macros that are available to users for use in the code or for conditional compiling. Macros for use in the code can be used anywhere in the code without restriction. In contrast to C, macros may be used freely within string constants, identifiers for variables, and function names. They always begin and end with a % character, and they are primarily used to write generic programs.

Available code macros include the node name, index of the current channel, name of the current network and the type of bus being used. The code can access the name of the containing file with %FILE_NAME%, or it can access the name of the program file currently being compiled with %BASE_FILE_NAME%. In the case of Include files, the latter is the parent file.

Here are two simple examples:

write("The node name is %NODE_NAME%");
putValue(envChannel%CHANNEL%Var1, %CHANNEL%);

There is a separate set of predefined macros for the conditional compiling of code sections. They are #if, #else, #elif or #endif. Within a program, they allow distinguishing between the program types simulation node, measurement node and test program as well as the CANoe version that is used.

Here is an example that uses a #pragma message:

#pragma message(“This program needs at least CANoe V 8 “)

#pragma message: The #pragma message directive lets users output their own message during the compiling process, e.g. the version number of the currently compiling CAPL program. It appears together with the other messages, warnings, errors, and general messages of the compiler.

Associative Arrays

Unlike languages such as C, CAPL does not support any pointer objects as a reference data type and therefore has no dynamic memory management. This makes CAPL very robust, and therefore well-suited for runtime environments that are short on memory and difficult to debug. In particular, CANoe's "CAPL-onBoard" feature benefits from this; in order to improve real-time behavior, it executes programs directly on certain hardware bus interfaces. Having said that, memory is seldom in short supply in the Windows' runtime environment. Therefore in this runtime environment CAPL offers associative arrays that can be used to store data even if the amount of data to be stored is unknown at the program start.

Associative arrays are containers which are equivalent to maps or dynamic arrays of other programming languages. Internally, CAPL uses an efficient hash table for these arrays. Consequently, these special arrays enable saving bus messages or measurement values, even if it is unknown in advance which messages or how many measurement values will occur.

In CAPL, associative arrays are declared as simple arrays, but with a key type instead of the otherwise usual size entry.

Two examples of associative arrays:

long lastTime [long];
char[30] translate[ char[] ];

The variable lastTime is an array that maps long keys to long values. While translate maps string keys (without length limitation!) to string values up to 30 characters. The following example uses lastTime to store a time value for each message ID occurring on the CAN network:

on message CAN1.*{
  lastTime []
    = this.time;

To enhance the user's experience, CAPL provides the following list of methods for associative array variables using dot notation:

  • containsKey queries whether a specific key is already contained
  • size returns the number of contained keys
  • clear fully empties an associative array, while remove removes one key from the associative array. In fact, remove and clear free up memory.


Finally, there is a special form of the for instruction for associative arrays. This form iterates over all keys actually contained in lastTime:

for (long akey: lastTime)
  {[…]} …

Access to Databases

In the introduction section we already illustrated the primary use of bus-specific databases in CAPL: they make it possible to introduce names for messages and signals. From a programming perspective, the complicated aspect of signals is that they are usually tightly packed in the data payload of messages for efficiency reasons. Therefore, signals generally exhibit arbitrary bit lengths and positions within the data payload of a message. They can also be stored in either Intel or Motorola format.

Symbol-based access via a signal name relieves the CAPL user of all of these details. In the case of reading or setting a signal value, the CAPL compiler automatically accounts for the signal's precise bit pattern that may include masking, swapping and shifting the bits.

To enhance user friendliness, other definable objects in the database may improve the linguistics of CAPL programming. For example, symbolic value tables may be associated with signals to use plain text names for signal value states. Furthermore, authors of a database have the freedom to define other attribute objects and to use them in the program code.

CAPL is able to use database objects directly based on their symbolic names. However, sometimes the potential objects of interest are not known at the time of program implementation. Therefore, the CAPL user may dynamically access the symbolic names and properties such as message names and identifiers transmitted by a network node.

A brief example:

message * m;
int i, mx;
for (i = 0; i < mx; ++i)

These symbolic access methods allow the user to implement generic programs – together with the previously introduced associative arrays.


Most CAPL programs must meet non-trivial real-time conditions. The execution model of a node simulated with CAPL even follows the model concept that CAPL programs can be executed at any speed. To adequately approach this ideal, CAPL programs are compiled, i.e. they are compiled into the machine language of the specific executing microprocessor. Moreover, optimized code sequences are used for the often complex access to signals. Below are a few tips on how the user can affect performance.

writeEx(): the write function is used to output specific texts to the Write window in CANoe and CANalyzer. As an alternative, the writeEx function is available for outputting larger quantities of data.

For one, it can be used to write directly to the Trace window or to a log file. The text output generated by writeEx is in all respects treated like a bus event, including the high priority processing and synchronizing the time stamps with real bus events.

Event procedures: a CAPL program consists of a combination of procedures that react to events. Some of these events may occur very frequently. Therefore, a program's performance is significantly better if only those events get processed, which are concerned. For example, if the user is only interested in those FlexRay slots that contain a specific signal, it is more efficient to define on frSlot signalname than on frSlot *.

Signal edges: there are two event procedure versions for signals and system variables. on signal_update and on sysvar_update are called with each write access to the specific data objects, even if the object's value hasn't changed at all. By contrast, on signal_change (on signal in short) and on sysvar_ change (on sysvar in short) offer a performance advantage if only signal edges are to be handled. Those event procedures are optimized to trigger on value changes only.

Memory Needs

Unlike most block-oriented languages, such as C, all locally defined variables in CAPL are static by default. This means that they are all created at the program start, and memory used to store these variables is not freed until the end of the program. Consequently, CAPL may require a surprisingly large amount of memory if many event procedures define the same type of large variables, which they could actually share.

An example:

testcase test789()
  char outBuffer[1024];

There are CAPL programs with thousands of such test procedures, of which only one may be executed at any given time. Rather than defining a large local variable of the same type in each event procedure, defining the large variable once globally in the Variables section utilizes a lot less memory.

Another inadvisable practice is to create very large arrays, e.g. to store event data under the respective message IDs. An extended ID in CAN comprises 29 bits, so it can assume over 500 million values. To define an array for this purpose would be a waste of memory. In such cases, it is better to use associative arrays as described above. Although associative arrays need somewhat more memory for each key that is actually used, they do not need any memory for keys that are not used.

Useful, Relatively Unknown Features

Finally, a brief list of some little-known CAPL features:

  • Structs can be used to define structures, similar to the approach in C. Together with copying operations, which can also convert Intel and Motorola formats within a struct, they represent a flexible method for data conversion.
  • When CAPL functions are called, the user has the option of passing reference parameters in addition to value parameters. Reference parameters make it possible to return more than one result value from a function. Reference parameters can also be used within CAPL–DLLs.
  • CAPL programs should also not crash in case of faulty usage. On one hand, this robustness is attained by the language structure, since there are no general pointers.
  • On the other hand, stability is improved by automatic runtime checks of array limits, stack limits and the necessary computing time. A separate command-line version of the compiler is available. This version is very helpful in automating sequences in script languages.

More CAPL Know-How

Visit our training website to find a CAPL training for CANoe or CANaylzer that suits you.

We also offer CAPL trainings in combination with vTESTstudio. Take a look at what we have to offer.

If you have any questions, please do not hesitate to contact our training staff.

Show more



Developing and testing ECUs and entire networks on highest level.

Go to Page

ECU and network analysis on highest level

Go to Page