Modbus and CAN bus workbench
Build and decode Modbus RTU, ASCII, and TCP frames, decode registers in every word order, draw CAN bit streams with stuff bits and CRC-15, calculate MCP2515, ESP32 TWAI, STM32, and SJA1000 bit timing, estimate bus load, and decode DBC signals, candump logs, OBD-II PIDs, and J1939 IDs.
Added · updated 28 October 2026
Works with
- Packet capture viewer (mini Wireshark) Networkopens a Modbus TCP frame from a capture here
How to use it
Modbus
Modbus frames builds a request once and shows it in all three framings. RTU adds a
CRC-16 sent low byte first. ASCII is : followed by hex, then an LRC (the two’s complement
of the byte sum) and CR LF. TCP puts a 7-byte MBAP header in front (transaction id,
protocol 0, length, unit id) and has no checksum. The RTU timing line gives the frame time
and the 3.5-character silent gap, which is fixed at 1.75 ms above 19200 baud. Paste any
frame into the decoder. It detects the framing, checks the CRC, LRC, or MBAP length, and
decodes functions 1–6, 8, 15, 16, 22, 23, and 43/14 (device identification). It also
explains exception responses. For a plain RTU CRC, use the
CRC tool.
Registers shows a block of 16-bit registers as every common type under all four word/byte orders. ABCD is big-endian, the Modbus default. CDAB swaps the words, which many PLCs and energy meters do. BADC swaps the bytes inside each register, and DCBA is fully little-endian. Turn on "start a value at every register" to find a value that is off by one register. The register map turns a response into named, scaled values. Write one line per register: address (0-based, or a 40001-style reference), name, type, scale, unit, and an optional order. The encoder turns a number into the registers to write.
CAN
CAN frame draws the whole classic frame, bit by bit. Stuff bits are highlighted, and a logic trace runs underneath. It also gives the CRC-15 (polynomial 0x4599, computed over SOF to the end of the data before stuffing), the frame length, and the time on the wire. The default frame is the published example (ID 0x014, one data byte 0x01, CRC 0x7753, three stuff bits) from Ken Tindell’s oscilloscope capture, which is used on Wikipedia. The CAN-FD table maps DLC 9–15 to 12–64 bytes. Its frame times are estimates that leave out dynamic stuff bits.
Bit timing lists every prescaler and segment split that gives the bit rate from your controller’s clock. The list is ranked by rate error, then by distance from the target sample point (87.5 % is the CiA recommendation for CANopen), then by more time quanta per bit. Click a row to get register values for that controller:
-
MCP2515: CNF1–3, with TQ = 2·(BRP+1)/Fosc.
-
ESP32 TWAI: a
twai_timing_config_tinitialiser. -
STM32 bxCAN: the BTR value and the HAL fields.
-
SJA1000: BTR0 and BTR1.
The decoder works the other way. For example, the MCP2515 values 00 F0 86 at 16 MHz, used
by the MCP_CAN Arduino library, are 500 kbit/s with a 56 % sample point and triple
sampling.
Bus load totals the bits per second of a message list. A classic frame without stuffing is 47 + 8n bits (11-bit ID) or 67 + 8n bits (29-bit ID), counting the 3-bit interframe space. The worst case adds ⌊(34 + 8n − 1)/4⌋ or ⌊(54 + 8n − 1)/4⌋ stuff bits.
DBC + candump parses BO_, SG_ (Intel and Motorola byte order, signed, factor and
offset, units, simple multiplexing), VAL_, and comments. It decodes logs in either
candump format: (ts) can0 123#DEADBEEF (candump -l, including ## CAN-FD frames) or
can0 123 [4] DE AD BE EF. Pick a signal to plot it over time. Frames that aren’t in the
DBC are tried as J1939 or OBD-II.
OBD-II + J1939 decodes mode 01 responses for about 60 common PIDs (formulas from SAE J1979, as listed on Wikipedia’s OBD-II PIDs page) and builds the 0x7DF request. It also splits a 29-bit J1939 identifier into priority, PGN, and source and destination addresses, and decodes a few common SPNs (EEC1 engine speed, ET1 coolant, CCVS speed, and others).
Limits
Modbus decoding guesses whether a frame is a request or a response from its length. You
can override the guess. DBC support covers the common subset: extended multiplexing,
signal groups, and float signals (SIG_VALTYPE_) are not decoded. The TWAI prescaler range
shown is the original ESP32’s. Later chips allow larger even prescalers.
Sharing
Share link copies a URL that opens this tool with your current settings — every value it remembers between visits, packed into ?s=. Opening a link replaces your saved settings for this tool. You can also write a short link by hand with frame (a Modbus frame to decode), for example /tools/modbus-can/?frame=01%2003%2004%2000%2064%2000%20C8%20BA%207A.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.