STM32 CAN Bus Communication Guide

STM32 CAN Bus Communication Guide

bxCAN Architecture, Bit Timing, Filters, Mailboxes, RX/TX & Firmware

1. Introduction — CAN as the Industrial Backbone

The Controller Area Network (CAN) is the de-facto physical layer for automotive and industrial networking: robust, differential, multi-master, and able to operate over twisted pairs at data rates up to 1 Mbit/s (classic CAN) with deterministic arbitration. On the STM32 family the CAN controller is the bxCAN peripheral — shared by F1, F2, F4, F7, L4 and many others, with the newer FD-capable variants adding larger frames. This guide covers the bxCAN memory-mapped architecture (mailboxes, filters, acceptance), the bit-timing calculation that any working node must get right, the configuration sequence for initialization, sending and receiving with interrupts and DMA, the filtering/acceptance-mask logic, loop-back testing, common firmware and hardware mistakes, and an FAQ. It pairs the peripheral knowledge with the clocking discipline described in the STM32 clock configuration guide, since the CAN peripheral clock must be derived correctly for the bit timer.

2. The bxCAN Architecture

The bxCAN peripheral implements the CAN 2.0A/2.0B protocol with three transmit mailboxes (each holding a full message), two receive FIFOs (FIFO0, FIFO1) of three mailboxes each, and a bank of filter registers that decide which incoming frames are copied into the FIFOs. The key idea is hardware acceptance filtering: the CPU is not interrupted for frames it does not filter in, so a node can be a quiet listener that only wakes for its own identifiers. The status/control registers (CAN_MCR, CAN_MSR, CAN_TSR, CAN_RF0R/RF1R, CAN_IER) implement the standard initializer, normal, sleep and communications states; the error status and timeout logic live in CAN_ESR and CAN_BTR.

3. CAN Bit Timing — the Calculation That Cannot Be Skipped

The CAN bit time is divided into quanta, and the position of the sample point decides noise immunity on the bus. The total bit time = 1 + Sync_Seg + (Prop_Seg + Phase_Seg1 + Phase_Seg2), each in units of time quanta (tq), where the tq is derived from the APB clock divided by the prescaler:

tq = PCLK / (BRP + 1),   bit_time = tq · (1 + TS1 + TS2),   f_bit = PCLK / ((BRP+1)·(1+TS1+TS2))

For a 50% nominal sample point the common recommendation is SJW=1, TS1 (sync+prop+phase1) = 13, TS2 = 2 for 1 Mbps on an 8 MHz APB→PCLK: 8e6/(1+13+2) = 500k… rather use the formula with the actual PCLK. The practical flow: pick PCLK (e.g. 36 MHz on F1 with PLL /2), set BRP so that tq = 0.1 bit, then TS1+TS2 to total 10 tq. The bit clock must not deviate more than the oscillator tolerance shared by all nodes — on the internal HSI RC this is often marginal for 1 Mbps, so prefer the external crystal (HSE) when the bus speed is high; the STM32 clock configuration guide shows how to route and verify the system/APB clocks.

Confirming the peripheral clock divider arithmetic (APB prescalers, PLL VCO) is exactly what the STM32 clock configuration calculator automates: enter the HSE frequency and target APB1 clock, and it returns the PLL/Prescaler chain so the CAN prescaler math starts from a verified PCLK rather than a guessed one.

4. Initialization Sequence

Configuring bxCAN always follows the same order: exit sleep → enter initialization mode → set timing (CAN_BTR) → configure filters (CAN_FMR/FFMR/FS1R/FM1R/FiR) → request normal mode and wait for the mode-acknowledge. A compressed F4-style setup:

// 1. Enable clocks
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// 2. Pinmux: CAN1_RX=PB8 AF9, CAN1_TX=PB9 AF9
// 3. Enter init mode
CAN1->MCR |= CAN_MCR_INRQ;
while(!(CAN1->MSR & CAN_MSR_INAK));
// 4. Bit timing: PCLK1=36MHz, 1Mbit -> BRP=3, TS1=14, TS2=1, SJW=1
CAN1->BTR = (1<<24) | (0xE<<16) | (0x0<<20) | (3 & 0x3FF);
// 5. Filters: accept all
CAN1->FMR |= CAN_FMR_FINIT;
CAN1->FS1R |= 1;          // FIFO0 scale 32-bit
CAN1->FM1R |= 0;          // mask mode
CAN1->FMR &= ~CAN_FMR_FINIT;
// 6. Normal mode
CAN1->MCR &= ~CAN_MCR_INRQ;
while((CAN1->MSR & CAN_MSR_INAK));

After exit-init, verify the mode bit before transmitting; transmitting too early (before the controller reports normal mode) silently loses frames.

5. Transmit — Mailbox Handling

A transmission is requested by writing the TX mailbox registers (CAN_TI0R/TDT0R/TDL0R/TDH0R) and setting the TXRQ bit; the empty mailbox is selected by checking CAN_TSR’s TME bits. The completion is best handled with the transmit-mailbox-empty interrupt, clearing the status before reusing the mailbox:

if (CAN1->TSR & CAN_TSR_TME0) {
    CAN1->sTxMailBox[0].TIR = 0x123 | CAN_TIxR_TXRQ;
    CAN1->sTxMailBox[0].TDTR = 1;
    CAN1->sTxMailBox[0].TDLR = data;
}

Error states (CAN_TSR ABRQ/TERR) must be serviced — a stuck mailbox with the abort bit pending blocks all further transmits. For high-throughput periodic frames, triple-buffer the mailbox logic or queue messages in RAM and let the TX-empty ISR drain the queue.

6. Receive — FIFO and Interrupt/DMA

Received frames land in FIFO0/FIFO1; enable the FIFO0 message-pending interrupt (FMPIE) and service the mailbox:

if (CAN1->RF0R & CAN_RF0R_FMP0) {
    id  = CAN1->sFIFOMailBox[0].RIR >> 21;
    dlc = (CAN1->sFIFOMailBox[0].RDTR >> 16) & 0xF;
    data= CAN1->sFIFOMailBox[0].RDLR;
    CAN1->RF0R |= CAN_RF0R_RFOM0;   // release mailbox
}

Overrun (FOVR) indicates the CPU stalled; if frames are dropped the application must either raise ISR priority, use DMA for the FIFO, or speed up service. For deterministic streaming, the DMA stream allocator helps map the available DMA streams onto the CAN/DMA transactions without conflicting with the ADC, USART and timer channels already reserved on the same DMA controller.

7. Acceptance Filters

Each filter bank can be configured in identifier-list or mask mode, 32-bit or 16-bit. Mask mode matches a range: e.g. to accept IDs where the high 8 bits equal a base ID, set the ID register to the base (top-aligned) and the mask to 0x7FF8. List mode matches exact IDs. The filter chain selects FIFO0 or FIFO1 per bank; combined filters give an effective “receive this family, drop the rest”. A common firmware error is leaving the filter in its reset state (which drops everything) and then wondering why no frame arrives — always write at least one filter bank that accepts the intended IDs.

8. Worked Example — 500 kbit/s Node on APB1 = 36 MHz

Target: node at 500 kbit/s, HSE 8 MHz, system/PCLK1 = 36 MHz.

  • Bit time budget: 16 tq/bit → tq = 1/500k/16 = 125 ns → BRP = 36e6·125e-9 − 1 = 3.5 → use BRP=4 (tq=138.9 ns, bit=16 tq → 444k…). Instead choose 20 tq/bit: tq = 100 ns, BRP = 36e6·1e-7 −1 = 2.6 → BRP=3 → tq=111 ns → 20 tq = 2.22 µs → 450k. The nearest clean combination: BRP=3, TS1=13, TS2=2, SJW=1 gives 36e6/(4·(1+13+2)) = 562.5k.
  • Take the scheme with the exact divisor: for 500k on 36 MHz use BRP=3, tq=0.111 µs? Instead pick 500k = 36e6/(BRP+1)/(1+TS1+TS2). With (BRP+1)=9 and (1+TS1+TS2)=8 → 36e6/72=500k. Set BRP=8, TS1=6, TS2=1, SJW=1, sample=6/8=75%.
  • Verify with the clock calculator that PCLK1 is really 36 MHz (PLL settings), then load CAN_BTR.
  • Enable CAN1 and GPIO clocks, set PB8/PB9 as AF9, configure the accept-all filter, enter normal mode, and send a loopback frame; a loop-back test (CAN_MCR_LBK) verifies the peripheral without a second node on the bus.
  • Probe on a scope between CAN_H and CAN_L: recessive = 2.5 V/2.5 V, dominant ≈ 3.5 V/1.5 V at 500 kbit/s; check the sample point timing.

9. Common Mistakes

  • Wrong bit timing / sample point: a deviating bit position causes sporadic arbitration errors even on a short bus.
  • Using the internal HSI RC at 1 Mbit/s: RC drift across temperature moves the node outside the bus tolerance; use an external crystal or a CAN-tolerant clocking scheme.
  • Forgetting a filter: with no configured filter bank the controller drops every frame.
  • Transmitting before normal mode: the TXRQ on a non-operational controller is ignored; always wait for the INAK clear.
  • No transceiver: the STM32 CAN is a protocol controller — it needs an external transceiver (e.g. TJA1050/SN65HVD230) with the correct 120 Ω termination at each bus end.
  • Ignoring bus-off: 256 consecutive error frames put the node into bus-off; the application must detect and recover to avoid a permanently silent node.

10. FAQ

Q: Do I need a transceiver? A: Yes — the bxCAN controller outputs digital TX/RX; the transceiver converts them to the differential CAN_H/CAN_L levels and drives the bus; the 120 Ω terminations at both ends of the cable are mandatory.

Q: What is the maximum speed? A: Classic CAN 1 Mbit/s (CAN 2.0), CAN FD up to several Mbit/s data phase with bit-rate switching; the practical cap depends on the bus length and transceiver ratings.

Q: Why does my node lose frames under load? A: Usually receive FIFO overrun (missed release) or an acceptance filter dropping the frame; check FOVR and the filter mask with a logic analyzer.

Q: Can multiple STM32 share one bus without a master? A: Yes — CAN is multi-master; arbitration by ID ensures the highest-priority frame wins without a central scheduler.

11. Conclusion

The bxCAN peripheral is reliable once its timing, filters and interrupt/DMA service are set correctly. Verify the APB clock with the clock calculator, calculate the bit timing precisely, configure at least one acceptance filter, add the transceiver with proper bus termination, and test in loop-back before wiring the twisted pair. That procedure turns a random “doesn’t receive” mystery into a working node on the first try.

发表评论