Automotive
CAPL Programming
CAPL (CAN Access Programming Language) is the C-like scripting language built into Vector's CANoe and CANalyzer tools — the standard way to simulate ECUs that don't exist yet, automate a test sequence, or script exactly the kind of CAN and UDS exchanges covered earlier, without writing a full standalone application.
- What it is
- A C-like, event-driven scripting language built into Vector CANoe/CANalyzer for simulating, testing, and analyzing automotive bus networks.
- Mental model
- Not a general-purpose language — its whole structure is "when this event happens, run this code," tightly bound to the bus-simulation environment it runs inside.
- Key numbers
- Runs only inside CANoe/CANalyzer, never standalone; event handlers, not a linear
main(), are the fundamental unit of a CAPL program. - Reach for it when
- Simulating an ECU that doesn't exist yet, automating a repeatable test sequence, or scripting a diagnostic exchange for validation.
Why a dedicated scripting language?
When one ECU is under development, the rest of the vehicle's network frequently doesn't exist yet — other ECUs may not be built, available on the bench, or even finished being designed. CAPL lets an engineer simulate the missing nodes' bus behavior — sending the messages a real ECU would send, responding the way a real ECU would respond — so the ECU actually under test can be exercised realistically, entirely inside CANoe/CANalyzer, without every other real ECU physically present.
Event-driven structure
A CAPL program has no single linear main(). Instead it's
a collection of independent handler blocks, each triggered by
something happening on the bus or in the simulation environment:
on message <name>- Runs whenever a specific CAN message is received on the bus.
on timer <name>- Runs when a timer expires — the standard way to send something periodically.
on key '<char>'- Runs when a key is pressed in the CANoe UI — handy for manually triggering a test step.
on start- Runs once when the measurement/simulation starts — the usual place to arm the first timer.
A worked example: implementing the UDS +0x40 rule
This ties directly back to UDS's positive response rule — here it is, actually implemented as a CAPL event handler that answers a Read Data By Identifier request for a VIN:
variables
{
msTimer periodicTimer;
}
on start
{
setTimer(periodicTimer, 100); // fire every 100 ms
}
on timer periodicTimer
{
message EngineData msg;
msg.RPM = 2500;
output(msg);
setTimer(periodicTimer, 100); // re-arm for the next period
}
on message DiagRequest
{
// SID 0x22 (Read Data By Identifier), DID 0xF190 (VIN)
if (this.byte(0) == 0x22 && this.byte(1) == 0xF1 && this.byte(2) == 0x90)
{
message DiagResponse resp;
resp.byte(0) = 0x62; // 0x22 + 0x40 -- the UDS positive-response rule
resp.byte(1) = 0xF1;
resp.byte(2) = 0x90;
// ... VIN bytes follow ...
output(resp);
}
}
Nothing here is exotic — it's the exact same request/response logic from the UDS page, just expressed as "when this specific message arrives, check its bytes, then send this specific response back."
Restbus simulation
Simulating the "rest of the bus" around one real device under test is one of CAPL's primary jobs — CANoe stands in for every other ECU on the network well enough that the real hardware behaves as if it were on a fully populated vehicle:
Real-world applications
- Restbus simulation — exercising one real ECU on a bench as if the whole vehicle network were present, per the diagram above.
- Automated regression testing — scripting known input sequences and asserting the expected CAN/UDS responses, repeatably and without a human operator.
- Diagnostic test automation — scripting the exact UDS request/response sequences from the UDS page for repeatable validation instead of manual tool operation.
- Fault injection — simulating a sensor failure, a malformed frame, or a bus-off condition to verify how the real ECU under test actually reacts.
Gotchas
- CAPL only runs inside CANoe/CANalyzer — it isn't a portable, standalone language, and a script can't run outside the Vector toolchain.
- Event handler ordering and shared global state between handlers is a real, recurring source of subtle bugs — conceptually similar to the shared-state hazards covered in Interrupts, just in a simulation environment instead of real hardware.
- Simulation code deserves the same rigor as production code — a bug in a restbus simulation script can make a perfectly good real ECU look broken, or worse, make a broken one look fine.
- CAPL scripts and the CAN database (DBC) files defining message layouts need to stay in sync — a stale DBC after a real message layout changes is a common, confusing source of simulation-vs-reality mismatches.