The CAN bus is a very interesting medium-speed “interconnect”, for various reasons:

CAN stands for Controller Area Network.


There’s perhaps no better source than the Wikipedia link above for a quick overview:

Development of the CAN bus started in 1983 at Robert Bosch GmbH. The protocol was officially released in 1986 at the Society of Automotive Engineers (SAE) conference in Detroit, Michigan. The first CAN controller chips, produced by Intel and Philips, came on the market in 1987. Released in 1991 the Mercedes-Benz W140 was the first production vehicle to feature a CAN-based multiplex wiring system.

Bosch published several versions of the CAN specification and the latest is CAN 2.0 published in 1991. This specification has two parts; part A is for the standard format with an 11-bit identifier, and part B is for the extended format with a 29-bit identifier. A CAN device that uses 11-bit identifiers is commonly called CAN 2.0A and a CAN device that uses 29-bit identifiers is commonly called CAN 2.0B. These standards are freely available from Bosch along with other specifications and white papers.

In 1993, the International Organization for Standardization (ISO) released the CAN standard ISO 11898 which was later restructured into two parts; ISO 11898-1 which covers the data link layer, and ISO 11898-2 which covers the CAN physical layer for high-speed CAN. ISO 11898-3 was released later and covers the CAN physical layer for low-speed, fault-tolerant CAN.

Article series

This is the first of what I expect to become a multi-part article series on the CAN bus. I’d like to describe the features of CAN which I find particularly elegant and useful, and will introduce a simple driver I have implemented for it as part of the JeeH library. Along the way, I’ll try to illustrate its use with a variety of small demo apps, running on either a Blue Pill (i.e. F103), or one of the STM32F4 µC families.

The big picture

But before diving in, let’s first cover the bigger context. I’m not going to adopt the jargon and terms used in the “official” CAN bus documentation, nor in the automotive industry, where it all started and is still being used. Every car today probably has at least one CAN bus subsystem. One reason for this popularity is obvious: connecting multiple devices in a bus saves a lot of point-to-point wiring, and copper is a scarce resource!

The wiring is really simple, somewhat similar to Ethernet, in that it is entirely passive:

With no devices connected, CAN-Hi and CAN-Low will have the same voltage level (it’s not even important what level). Each device can pull the two apart, i.e. pull CAN-Hi a bit towards Vcc and CAN-Low a bit towards GND. Again, it doesn’t really matter that much what Vcc is and how GND is referenced. Only the difference matters, within reason.

Ok, some terminology is unavoidable: the CAN bus state can be either “dominant”, i.e. with lines pulled apart, or “recessive”, i.e.lines pulled together by the 120 Ω termination resistors (of which there must always be two, one each at the far ends of the bus).

The key feature of this is that if you equate “dominant” to “0”, then the entire CAN bus can be seen as a long logical AND gate. Any device can make it “0”, no-one can force it to “1”. This is used to great effect for addressing, prioritising, and managing bus-contention.

The CAN bus is not a low-power bus: pulling the two lines 3V apart, and given the 60 Ω combined termination resistance, a total of 50 mA current will flow. Then again, these resistor values and currents are also what makes the CAN bus less susceptible to noise.

The voltage levels, current requirement, and potential voltage spikes are such that the CAN bus cannot be tied directly to a µC chip (with one exception: NXP’s “LPC11C24”). A simple CAN transceiver driver chip such as the MCP2551 is needed for each node. On the plus side, that particular chip can withstand up to ± 42V spikes, making this a very robust “front gate” when there are long bus lines or in very electrically noisy environments.

Note that there is a way to avoid these extra chips for short-range use, with a variant based on “Single-wire CAN” (SW-CAN). But that topic will be covered at a later time.

The first puzzle we’ll need to solve is how to deal with multiple transmitters on this shared bus. We obviously need a mechanism which doesn’t mess up whatever is currently being sent by some other node on the bus, yet knows when to start “dominating” our CAN bus.