- October 27, 2026
Not enough time? Get the key points instantly.
The board passed bring-up weeks ago. Now the field unit drops a CAN message every few hours, the error counter creeps up overnight, and nobody can reproduce it on the bench.
Random fixes cost more when you debug CAN bus communication issues than almost anywhere else in embedded work. Swap a transceiver, rewrite the driver, add a ferrite, and you still don't know which change helped, or whether the fault will return after the product ships.
By the end of this post, you'll know how to read what the bus is already telling you through waveforms, error codes, and firmware counters, so you can trace any CAN fault to its layer before you change a single part.
A dead bus is the easy case. If nothing moves at all, a fixed checklist of termination, wiring, transceiver mode, and bit rate finds the fault quickly. We covered that in 10 checks for a CAN bus not communicating.
The expensive faults are partial. Some frames arrive and others don't. One node goes bus-off once a day. Traffic runs fine until a motor starts. These faults survive checklists because every static measurement looks correct.
CAN gives you more diagnostic data than almost any other embedded bus, though. Every controller counts its own errors, classifies the last one, and signals every failure on the wire with an error frame. You can debug CAN bus communication issues reliably when you collect that evidence in order:
Waveform evidence: what the electrical signal actually looks like at the receiver
Protocol evidence: which error type the controller reports, and which node reports it
Firmware evidence: what your own code does with frames once they arrive
Each source rules out a layer. Together, they point to the fault.
Effective CAN bus debugging needs more than one instrument, because no single tool sees the whole problem. A CAN analyzer shows clean frames while your firmware drops half of them. A scope shows perfect edges while a filter discards the frame you need.
Tool | What It Sees | What It Misses | Best For |
|---|---|---|---|
Oscilloscope (2 channels + math, or differential probe) | Voltage levels, edge shape, ringing, bit width, error flags | Frame content over long periods | Signal integrity and timing faults |
Logic analyzer on TXD/RXD | What the MCU sends versus what it receives back | Analog signal quality | Controller and transceiver interaction |
USB CAN interface (PCAN-USB, Kvaser, or similar) | Every frame, timestamps, error frames, bus load | Which node caused an error | Long-duration logging and traffic analysis |
Debugger with register view | Error counters, last error code, FIFO and mailbox state | Anything on the wire | Firmware-side faults |
To debug CAN bus communication issues on any project, keep at least a USB CAN interface and a scope with CAN decoding on the bench. The analyzer finds when the fault happens. The scope shows why.
The scope is where CAN bus debugging starts for any fault that affects more than one node. Probe CANH and CANL on two channels and display the math difference (CH1 − CH2). A single-ended probe on CANH alone hides common-mode problems, so always look at the differential signal.
ISO 11898-2 receivers read a differential voltage below 0.5 V as recessive and above 0.9 V as dominant. A healthy transmitter drives roughly 1.5–3.0 V differential into a 60 Ω bus. Measure at the receiving node, not the transmitter, because cable resistance and ground offset reduce the margin at the far end.
Waveform Feature | What It Points To |
|---|---|
Ringing on every edge | Missing or misplaced termination, long stubs |
Rounded, slow edges | Excess bus capacitance, too many nodes, or a slope-control resistor set too high |
Dominant level below ~1.5 V differential | Weak transceiver, high harness resistance, or extra termination loading the bus |
CANH and CANL both shifted up or down | Ground offset between nodes |
Six or more dominant bits in a row | An active error frame, since normal traffic never allows more than five equal bits |
The last row is the most useful trigger in CAN bus debugging. Bit stuffing guarantees a level change after five identical bits, so a dominant pulse lasting six bit times (12 µs at 500 kbps) is always an error flag. Set your scope to trigger on a pulse wider than about 5.5 bit times and it will capture only the moments something goes wrong.
Add the MCU's TXD and RXD pins on two more channels. RXD should mirror TXD with a short delay, the transceiver loop delay.If TXD goes low but RXD stays high, the transceiver never drove the bus. Check its supply and standby pin. If RXD shows dominant bits your node didn't send, another node is driving the bus, which is normal during arbitration and suspicious anywhere else.
Loop delay also limits bus length. During arbitration, every node must see every other node's bit before the sample point. Transceiver delay plus cable propagation, roughly 5 ns per meter, sets the maximum distance at a given bit rate.
Error counters are the cheapest evidence when you debug CAN bus communication issues, because the controller already collects them. Every CAN controller keeps a transmit error counter (TEC) and a receive error counter (REC). A transmit error adds 8 to TEC, a receive error usually adds 1 to REC, and each successful frame subtracts 1. A slowly rising counter means errors arrive faster than successful frames can cancel them.
The trend tells you where to look:
TEC rising on one node only: that node's transmit path, its transceiver, or its bit timing
REC rising on one node only: that node's receive path, sample point, or clock accuracy
Counters rising on every node: shared wiring, termination, or an external noise source
Then read the last error code (LEC). On STM32 bxCAN it sits in the CAN_ESR register. FDCAN parts report it in the protocol status register. Each code points to a different layer:
LEC Value (bxCAN) | Error Type | Most Likely Cause |
|---|---|---|
1 | Stuff error | Bit timing mismatch, noise, or reflections corrupting bit boundaries |
2 | Form error | CAN FD frame on a classic CAN node, or a badly placed sample point |
3 | ACK error | No other node acknowledging, or receivers on a different bit rate |
4 | Bit recessive error | Node sent recessive but read dominant outside arbitration; another node or a fault holds the bus |
5 | Bit dominant error | Node sent dominant but read recessive; the transceiver is not driving the bus |
6 | CRC error | Noise or reflections corrupting data bits, or clock drift on a long frame |
A bit dominant error is almost always a hardware fault on your own board. Stuff and CRC errors usually point to signal integrity or timing on the shared bus. The LEC turns "CAN is flaky" into a specific layer in seconds.
Many teams debug CAN bus communication issues on the wire when the frames are actually lost inside their own firmware. The analyzer shows every frame on the bus, yet the application never sees some of them.
STM32 bxCAN has two receive FIFOs, each only 3 messages deep. If a burst of frames arrives while a higher-priority interrupt or RTOS task blocks your CAN handler, the fourth frame overwrites or drops a message, and the controller sets the FOVR overrun flag. The bus is perfect. Your code is too slow.
Fixes, in order of effort:
Drain the FIFO in the interrupt handler into a larger software ring buffer, and process frames in a task
Use both FIFOs, routing high-rate IDs to one and critical IDs to the other with acceptance filters
Raise the CAN interrupt priority above long-running ISRs
bxCAN has three transmit mailboxes. By default, the controller sends the pending frame with the lowest ID first, not the one you queued first. If your protocol depends on order, such as multi-frame transfers, set the TXFP bit for FIFO ordering or queue frames one at a time.
Enable the controller's error interrupts (on bxCAN: error warning, error passive, bus-off, and last error code). In the handler, log a timestamp, TEC, REC, LEC, and the bus state into a ring buffer. Expose that buffer over a debug UART or a diagnostic CAN frame.
A log like this turns an intermittent field fault into data, and it lets you debug CAN bus communication issues on units you can't physically reach. When a unit fails once a week, a few hundred bytes of error history tell you whether the cause was electrical, timing, or software, without a site visit.
Intermittent CAN errors always have a trigger. For this kind of CAN bus debugging, your job is to find what changes at the moment the error appears.
Log analyzer timestamps alongside system events: motor start, relay switching, a heater cycling, a vehicle crank. Errors that cluster around a load switching on point to electrical noise or ground shift. Errors that rise with temperature point to oscillator drift or a marginal sample point. Errors that follow vibration point to a connector or harness.
Remove nodes one at a time, or split the bus into two terminated segments. If errors stop when one node leaves, that node or its stub is the source. Divide-and-conquer finds a bad node faster than probing every board.
High CAN bus load causes faults that look like errors but aren't. CAN arbitration always lets the lowest ID win, so at high load the high-ID (low-priority) messages wait longer and longer, and eventually miss their deadlines.
Estimate load with simple math. A classic CAN frame with an 11-bit ID and 8 data bytes takes roughly 125 bits including typical stuffing. At 500 kbps, that's about 0.25 ms per frame.
Scenario | Frames per Second | Bus Load at 500 kbps |
|---|---|---|
20 messages at 10 ms period | 2,000 | ~50% |
30 messages at 10 ms period | 3,000 | ~75% |
40 messages at 10 ms period | 4,000 | ~100% (saturated) |
Most teams target a design load well below saturation to leave room for retransmissions and future messages. Your CAN analyzer reports live bus load, so confirm the math against a real capture.
Good CAN bus debugging follows the fault's pattern. Use the pattern to pick your first tool, then collect evidence before changing anything.
Symptom | First Tool | First Measurement |
|---|---|---|
Errors on every node | Oscilloscope | Differential waveform at the farthest node |
Errors on one node only | Debugger | TEC, REC, and LEC on that node |
Frames on the bus, missing in the app | Debugger | RX FIFO overrun flag and ISR timing |
Low-priority messages late or missing | CAN analyzer | Bus load and message timing |
Errors tied to a machine event | CAN analyzer + event log | Error timestamps against system events |
Errors that rise with temperature | Debugger + oven or field log | Clock source and sample point |
Then follow these rules on every debug session:
Capture evidence before changing hardware or code
Change one variable at a time and re-measure
Keep the error log running after the fix to confirm the counters stay flat
Write the root cause down, because CAN faults in one product tend to return in the next
Debugging CAN bus communication issues stops being guesswork the moment you read the evidence the bus already produces. Start with the waveform at the receiver, read the error counters and last error code, and instrument your firmware before you touch a single component. Intermittent faults always have a trigger, and continuous logging is how you find it.
If an intermittent CAN fault is holding up your release, CoreFragment's embedded team can review your scope captures, error logs, and controller configuration together, and tell you which layer the fault lives in before you commit to a respin.