Guides·CAN

Import a DBC file into an LVGL project

Turn a CAN database into typed signals, bind them to LVGL widgets, and watch live values in the simulator — no glue code.

A .dbc file describes your CAN or J1939 network: message IDs, signal layouts, scaling factors, units. Instead of hand-writing parsers and formatters, Protok Studio reads the database directly and exposes every signal as a typed source you can drop onto a widget. This guide walks through the whole path — from raw .dbc to a live gauge in the simulator.

1. Drop the DBC onto the canvas

  1. Open your project and switch to the canvas view.
  2. Drag a .dbc file from Explorer onto the canvas (or use the file manager import).
  3. Studio parses the file and lists every message and signal — with name, byte layout, factor, offset, and unit already resolved.

Nothing is copied: the project keeps a reference to the database, so when your system engineer pushes an updated .dbc, bindings stay intact and renamed signals are flagged instead of silently breaking.

J1939 works out of the box

J1939 PGNs, SPNs and source-address claims are handled natively — PDU1/PDU2 masks are applied for you. Point the importer at a standard J1939 database and the signals arrive with correct slot scaling.

2. Bind a signal to a widget

  1. Place a widget — a gauge, bar, label or arc — on a screen.
  2. Open its binding HUD and pick a signal from the imported database.
  3. Choose the target property: value for gauges, text for labels (with a format string), color for threshold indication.

Bindings are typed: Studio knows a signal is uint16 scaled to km/h, so a text binding can offer "{value:.0f} km/h" formatting without any script.

3. Drive it from a real trace

Load an .asc or .dpl CAN log in the simulator panel and press play. The WASM runtime decodes frames with your DBC, pushes signals through bindings, and the LVGL screen updates exactly as it would on the panel — including timing jitter and out-of-range behavior. This is the fastest way to validate layout and scaling before hardware arrives.

4. What lands in generated code

On export, Studio emits a static C99 decoder table from the DBC and a dispatcher that feeds bound widget properties — zero allocations, no dynamic lookups:

c · generated dispatch table
/* CAN message dispatch table — only messages referenced by bindings. */
typedef struct {
    uint32_t pgn;
    uint8_t  target_sa;
    bool (*handler)(const uint8_t *data, uint8_t dlc);
    const char *name;
} pl_can_msg_entry_t;

static const pl_can_msg_entry_t pl_can_msg_table[] = {
    { 0x0F004, 0xFF, EEC1_on_frame, "EEC1" },   /* EngineSpeed → rpm_gauge */
};

/* ISR-safe: latest frame per entry + dirty flags, polled by the UI worker.
 * J1939 PDU1 masking and factor/offset scaling are generated for you. */

Where to go next

The same binding pipeline works for TRDP datasets and raw CAN frames. See Using Studio for the full binding reference, or Generated code for what ends up in your firmware.