If you place a dozen people in a room – let’s say a bunch of CAN bus geeks – then more likely than not, a discussion will start to emerge. Interestingly, it’ll not be chaos: people will listen when someone else is speaking, and wait to interject a response. Most of the time.
Exactly the same happens on the CAN bus: transmissions start only when the bus has been idle for a little while, i.e. in recessive “1” state. This can be determined by always observing the CAN bus state, i.e. by keeping the receiver on at all times.
Furthermore, collisions can be reliably detected by “listening to our own voice”, so to speak. The transmission of a recessive “1” bit can only be successful when no other device transmits a dominant “0” bit at the same time.
All devices on the bus must use the same data rate. The CAN bus standard allows rates up to 1 Mbit/sec. At this rate, the longest distance between nodes must not exceed 40 m.
The reason for this is that all devices need to see the same signal to make valid decisions and to receive a good data stream. With 40 meters, there’s enough time within the bit-time sampling allowance for an electrical signal to travel back and forth between nodes, so that CAN’s AND logic effect can kick in
Lower data rates can be chosen to support longer cables, up to 1000 m at 50 Kbit/s.
This approach differs from Ethernet, where packet collisions cannot be ruled out, due to its much higher data rates (100 Mbit/s and up). By the time a node decides to start sending a new packet, another one might already be racing down the cable, towards it.
Here is a sample CAN bus packet (“frame” in CAN terminology) from the Wikipedia page:
I’ll skip some of the finer points of the packet structure, such as bit-stuffing, but three design details deserve an explanation (and lots of respect - it’s a brilliant protocol).
Collision-free bus access
With the CAN bus, transmit collisions are not possible. All nodes see the same state, and can make the same decision: to send or not to send, after a minimum idle period.
But this is only one side of the problem. What now? Let’s say two devices start sending at the same time, and at some point one of them sends a dominant “0”, while the other sends a recessive “1”. Since the CAN bus acts like an AND gate, the “0” will “win” and force the bus to zero. This also explains why it’s called “dominant”.
This is where the listen-while-you-talk approach comes to the rescue: a sending node which “lost” the bus (i.e. trying to get a “1” out) will notice that the bus does not match its desired state. And that’s where the clever design shows: the losing device immediately stops sending, and lets the other device proceed and complete its packet transmission.
Note that there was a collision of sorts, but it caused no damage or delay - the dominant bit still reached the bus unaffected, and its sender continued as intended. It didn’t (and couldn’t) even notice that a second sender had been briefly active at the same time!
As a consequence, even the nodes which tried sending at the same time but lost access will receive the packet against which they “lost”, and that packet will still be fully intact.
A built-in priority system
Each CAN bus packet consists of a number of essential parts:
- the dominant “0” start bit, which signals a new packet
- the “address” of 11 or 29 bits (the original 11-bit design was deemed too short)
- the packet data payload
- the CRC checksum
The address part is critical: each sender is obliged to use a different one. Because of this, the above logic AND “win-or-lose” mechanism will have turned off all but one transmitter by the time the entire 11- or 29-bit address has been placed on the bus.
This means that after getting through the address phase and “winning” each of its bits, the last transmitter standing now “owns” the bus. It can send whatever it likes from then on. As soon as the transmission finishes, the whole process starts over: all the remaining devices wait for the idle period, and then again try to gain control of the bus. And – by design – one of them will win again.
Since “0” is dominant, this means that lower addresses always win over higher ones. So the choice of address used as prefix of a packet also determines its priority!
Real-time bus access
The combination of dominant / recessive selection and address bits is what makes this a real-time bus. Note how a packet with address zero will always get through (all address bits are dominant “0”). The only thing it needs to do is wait for an idle period on the bus.
And that’s where the next clever design decision comes in: CAN bus packet payloads can only contain 0..8 bytes of data. At 1 Mbit/s, and accounting for some packet management overhead, this means that the bus will be idle at least every 100..150 µs.
Obviously, if the bus is flooded with address-zero packets, nothing else will get through. But with a bit of restraint, the CAN bus utilisation can be surprisingly high - 60..70% or so. In other words: a 1 Mbit/s bus can support a streaming rate of at least 600..700 Kbit/s.
Note also that this is a deterministic bus (unlike the stochastic behaviour of Ethernet and its exponential back-off to try and avoid collisions). The worst-case transmit delays for a given mix of packet streams and rates can be calculated in advance.
The way the CAN bus operates can be very confusing. Sending a “1” or a “0” on the bus might seem straightforward, but what about all this “AND logic”, “dominant”, “CAN-HI” vs “CAN-LO”, and inverted logic in general? It’s very easy to make mistakes with all this.
Here’s the deal - if you can remember at least a few of the combinations in the following list, you’ll stand a better chance of getting it right:
- dominant wins over recessive, always
- a zero bit (e.g. in the address) is dominant
- lower addresses have more leading zeros and dominate over higher addresses
- the idle state is when nothing is going on, or no devices are present
- idle bus lines are pulled together by the termination resistors
- pulled apart is my way of describing the dominant state on the bus
- CAN-LO is useful when viewing the bus as a single signal, low == dominant
- since zero wins, the bus acts like an AND gate, i.e. zero forces the bus
Placing a one on the bus has no effect. If the bus was recessive (bus-1 AND my-1 => 1), it will remain so. If the bus was dominant, it will also stay so (bus-0 AND my-1 => 0).
In the world of CAN, zero dominates, and always wins. There are no collisions. Every bit sent on the bus will come through (unless there is a strong electrical disturbance). It’s the opposite of egalitarian, but it sure makes effective use of the bus as a shared resource.