How to Debug CAN bus Communication Issues in Embedded Systems

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.

Why Debugging CAN Bus Communication Issues Needs a Method

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.

Build a CAN Debug Toolkit That Covers Every Layer

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.

Read the CAN Bus Oscilloscope Capture Correctly

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.

What a Healthy Waveform Looks Like

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.

Probe TXD and RXD at the Same Time

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.

Decode CAN Error Counters and the Last Error Code

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.

Instrument Your Firmware to Debug CAN Bus Communication Issues

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.

Watch for RX FIFO Overruns

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

Watch Transmit Order

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.

Log the Evidence Continuously

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.

Track Intermittent CAN Errors to Their Trigger

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.

Correlate With Events

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.

Divide the Bus

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.

Calculate CAN Bus Load

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.

Follow This CAN Bus Debugging Workflow

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:

  1. Capture evidence before changing hardware or code

  2. Change one variable at a time and re-measure

  3. Keep the error log running after the fix to confirm the counters stay flat

  4. Write the root cause down, because CAN faults in one product tend to return in the next

Conclusion

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.

Author

Parthraj Gohil

Parthraj Gohil is the Founder and CEO of CoreFragment Technologies. He run the team of IoT developers, embedded engineers, app developers and AI engineers. With more than 10 years of industry experience, he has delivered projects across Healthcare, Wearables, Industrial IoT, Consumer Electronics and Automotive.

Have Something on Your Mind? Contact Us : info@corefragment.com or +91 79 4007 1108

Share this blog

Share this on social channels to benefit others.