Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Current »


CAN BUS (Controller Area Network) is a very deterministic BUS heavily used in the automotive industry. It is a half-duplex BUS, that operates using a pair of differential signals. Typically, the speed standards are 100K, 250K, 500K or 1Mbit.

CAN BUS may have several tens of controllers on the same BUS and you can typically go relatively long distances such as 10 meters without compromising the speed or reliability. The message id of each message can address other nodes on a CAN BUS (more on this later).



Termination Resistors

There are two main reason why termination is required. First, it improves signal quality by removing reflections( oscillations) on the bit edges and prevents communication failure. When signal reaches at the end of the cable the reflections become strong, This is the reason why the termination resistors are kept at the ends. Second reason being, to achieve recessive level (defining a logic 1) in the communication.

CAN bus is a serial bus which transmits binary (0(dominant) or 1(recessive)) signals. When CAN Driver at CAN-node transmits recessive bit, it becomes completely passive. A passive component(i.e. resistor) is required as a 'pull-up' or 'pull-down' or both to a certain voltage level to achieve a required signal level during recessive bit transmission.

To protect signal from external noise, twisted pair wire is used as a transmission medium and to get certain voltage level at recessive level, a resistor is placed between two twisted wires. It ensures the required differential voltage level at dominant signal and also brought down the voltage level to zero when dominant signal disappears.

The appropriate resistor selection to define recessive level is a challenge. At the time of dominant signal transmission, achieving certain signal level is desired and the low resistor value demands high current. So, to reduce power consumption, the required resistor value should be higher. Higher resistance value comes with possible drawbacks. if the resistor value is higher, it will demand higher noise energy level to get to the dominant level and a lower noise threshold may prone communication stream to errors. also during dominant signal level the capacitor in the cable gets charged to certain level. So, before CAN-driver can transit from dominant to recessive level the capacitor should get discharged. and Hence, resistor value should be lowest possible for best performance.

As per CAN standard, the typical termination resistor value is kept at 120 ohm. the reason behind this is most of the automotive cables are single wires. if we take wires used in a car and twist them in a pair, the impedance of the twisted pair measures 120 ohms(approx.) and further squeezing the cable the impedance will drop to 105 ohms(approx.). So, as per this the 120 ohm resistance is not the optimal value but it is good enough for slew rate of 50ns at 1 Mbps. The same slew rate with 100Mbps is a problem but the bit rate of 100Mbps is far more than CAN-FD standard.

The termination resistor shall comply with the limits specified in below table:






Min: 100 Norm: 120 Max: 130

[Termination Resistor Figure]


CAN transceivers is an interface between the CAN protocol controller and the physical wires of the CAN bus lines.
It does mainly two tasks:

  • Receiving: It receives differential signal from the bus and converts it to the serial data signal expected by CAN controller. also it has protective circuit to protect the CAN controller.

  • Transmitting: It receives serial signal(bits) from the CAN controller and converts it to the differential signal that can be transmitted over typical CAN-bus.

Speed and Differential Signals

Bit Stuffing

Bit stuffing is technique of adding extra bits to communication packet which does not carry any information but assists in management of communication. It is used to ensure synchronization of all nodes.

During the transmission of a message, a maximum of five consecutive bits may have the same polarity. the transmitter will add an additional bit of opposite polarity in to the bit stream before transmitting new bits.

The receiver also checks for number of bits of same polarity and removes the stuff bit from the bit stream. this is called de-stuffing.

This technique is introduced in CAN because of Non Return to Zero(NRZ) coding scheme is adopted. It is used for an entire CAN data or remote frame with the exception of fixed form bit fields for the CRC delimiter, ACK field, and end of frame. CAN error or overload frames are also fixed form.

Any node receiving a message that breaks the bit stuffing rules (more than five consecutive recessive or dominant bits in a sequence that should be bit stuffed) will detect this as a receive error and take action dependant on the node state (for example, transmit an active or passive error frame).


ACK bit

The ACK bit is located between the CRC delimiter and the ACK delimiter in the CAN frame. The ACK bit is used by any nodes that receive a frame to indicate to the transmitter that it has been received successfully. When transmitting the frame the transmitter transmits a recessive signal (1) in the ACK bit, once a node successfully receives the data it transmits a dominant signal (0) at the ACK bit which overrides the transmitters recessive signal. This signals to the transmitter that the frame was received by at least one node. If you have multiple nodes the dominant signal will always override the recessive signal i.e. If you have two nodes and one signals a dominant ACK bit and the other a recessive ACK bit the dominant value will override the recessive. Thus, the transmitter has no way of knowing that all of the nodes have successfully received the frame. The transmitter will only know that at least 1 has or none of them have.

Message ID based Arbitration

The message ID for a given can frame is also used as the priority of the message being sent. A lower message ID has a higher priority because a logical 0 is a dominant signal and will override a logical 1, which is recessive. When a device starts sending out a message it does so by transmitting one bit and then observing the bus to see if the same bit is being sent. If it observes that a different bit is sent it knows that a higher priority message won the arbitration process and it stops transmitting. For example, lets say two devices begin transmitting at the same time. Device 1 is sending a message with id: 0b11000101101 and device 2 is sending a message with id: 0b11000001101. The following transmission sequence will occur:


Start Bit












Rest of the CAN frame

Device 1













No transmission

Device 2














Can Bus














As you can see above, device 2 won the arbitration process as it's message id is lower than the message id of device 1. Once device 1 did not see the bit that it sent on the bus it knew that it had lost the arbitration process and stopped sending bits altogether after sending bit 5.


Typically, messages are sent periodically, and asynchronously by the transmitters. In some cases however, a node might want to request data from the transmitter instead of the data being sent periodically. The node can do this by sending a remote frame to the transmitter which triggers the transmitter to send a data frame.

The remote frame and data frame differ in two ways:

  1. The data frame has the RTR bit set as a dominant signal and the remote frame has the RTR bit sets as a recessive signal

  2. The remote frame does not include a data field (DLC is set to 0(dominant))

If a data frame and a remote frame are sent with the same message ID then the data frame will simply win arbitration due to the RTR bit (which is the next bit after the ID) being a dominant signal.


CAN bus is fault tolerant and maintains a number of error counters for robust operation.

Transmit Error Counters

Receive Error Counters

Bus Off Conditions


  • Automotive

    • Trucking - J1939

  • Industrial


DBC file is a proprietary format that describes the data over a CAN bus. It is still less proprietary than developing your own standard hence is a good path for CAN applications. Furthermore, manufacturer's of sensors may just provide you the hardware and the DBC file to interface so it is a good format to use.

We will demonstrate the basic syntax of a DBC file that defines up to 8 bytes of CAN message data. A lot of CAN bus related tools can read the DBC file and display values next to each "signal" that you define in the DBC file.

Message Format

DBC file must contain a Message ID (MID), and at least one signal. Let's demonstrate by showing a message that contains a single 8-bit signal. Spaces and the syntax is really strict, so if you get a single space incorrect, the auto-generation script will likely fail.


BO_ 500 IO_DEBUG: 4 IO
 SG_ IO_DEBUG_test_unsigned : 0|8@1+ (1,0) [0|0] "" DBG


  • BO_ is a message syntax.

  • The message name is IO_DEBUG and MID is 500 (decimal), and the length is 4 bytes. (though we only need 1 for 8-bit signal)

  • The sender is IO.

  • SG_ is a signal syntax. IO_DEBUG_test_unsigned is a signal name.

  • 0|8: The unsigned signal starts at bit position 0, and the size of this signal is 8.

  • @1+: Defines that the signal is little-endian, and unsigned.

  • (1,0): Defines scale and offset. (discussed later)

  • [0|0]: Min and Max is not defined. (discussed later)

  • "": There are no units. (it could be, for instance "inches")

  • The receiver is DBG.

Signed and Unsigned Signals

A signed signal can be sent by simply applying a negative offset to a signal. Let's add a signed signal to the previous message.


  • @1-: Defines that IO_DEBUG_test_signed signal is little-endian, and signed.

Fractional Signals

A floating point variable can be sent by deciding the range, and the precision that you require. For example, if we choose 8-bits, with 0.1 as a fraction, we can send the data range of 0.0 -> 25.5. On the other hand, if we want more precision and negative representation, we could use 12-bits with 0.01 as a fraction, and an offset. The second fractional signal also contains an explicit minimum and maximum, which is limited by 12-bit that can represent 4096 different numbers, and by factoring in the offset, and using half of the range for negative representation, it ends up with the limited range of -20.48 -> 20.47.

BO_ 500 IO_DEBUG: 4 IO
 SG_ IO_DEBUG_test_unsigned : 0|8@1+ (1,0) [0|0] "" DBG
 SG_ IO_DEBUG_test_signed : 8|8@1- (1,-128) [0|0] "" DBG
 SG_ IO_DEBUG_test_float1 : 16|8@1+ (0.1,0) [0|0] "" DBG
 SG_ IO_DEBUG_test_float2 : 24|12@1+ (0.01,-20.48) [-20.48|20.47] "" DBG


  • Fractional signal is calculated as: [calculated value] = [offset] + [scale] * [raw value]

  • IO_DEBUG_test_float1: variable is calculated as 0 + 0.1 * [raw value].

  • IO_DEBUG_test_float2: variable is calculated as -20.48 + 0.01 * [raw value].

Little Endian Examples

Signals that are defined as Little Endian in the DBC are easier to edit manually without a UI based DBC editor. This is because when we indicate that an LSB of a signal is "4" and is a 14-bit signal, then it is easier to understand the bounds of this signals are b17 ... b4.

Example 1

BO_ 500 IO_DEBUG: 4 IO
 SG_ IO_DEBUG_test_unsigned : 0|8@1+ (1,0) [0|0] "" DBG
 SG_ IO_DEBUG_test_signed : 8|8@1- (1,-128) [0|0] "" DBG

Signal Layout

  • x denotes "start" position

  • <- indicates most significant bits, and end of the signal

  • Start of IO_DEBUG_test_unsigned: 0

    • End: length + start - 1 = 7

  • Start of IO_DEBUG_test_signed: 8

    • End: length + start - 1 = 8 + 8 = 15


             7   6   5   4   3   2   1   0
         0 |<-----------------------------x|
             +-- IO_DEBUG_test_unsigned
     B     +---+---+---+---+---+---+---+---+
     y   1 |<-----------------------------x|
     t     +---+---+---+---+---+---+---+---+
     e       +-- IO_DEBUG_test_signed

Example 2

 SG_ SENSOR_SONARS_left : 0|10@1+ (1,0) [0|800] "inch" DRIVER
 SG_ SENSOR_SONARS_right : 10|10@1+ (1,0) [0|0] "inch" DRIVER
 SG_ SENSOR_SONARS_middle : 20|10@1+ (1,0) [0|0] "inch" DRIVER

Start and end bit in terms of a uint64_t:

  • SG_ SENSOR_SONARS_left : 0|10

    • Start: 0, End: 9

  • SENSOR_SONARS_right : 10|10

    • Start: 10, End: 19

  • SENSOR_SONARS_middle : 20|10

    • Start: 20, End: 29

Signal Layout


             7   6   5   4   3   2   1   0
         0 |------------------------------x|
         1 |----------------------x|<------|
     B                               +-- SENSOR_SONARS_left
     y     +---+---+---+---+---+---+---+---+
     t   2 |--------------x|<--------------|
     e     +---+---+---+---+---+---+---+---+
                             +-- SENSOR_SONARS_right
         3 |   |   |<----------------------|
                     +-- SENSOR_SONARS_middle

If we re-arrange the bytes such that byte 0 is on the right hand side, and extract the 8-bytes of data into a uint64_t, then we have the full signal from where we can extract the CAN signal easily in a C program or equivalent. The Start and End bits are easy to compute for "Little Endian" DBC signal, as the 0|10 notation for SENSOR_SONARS_left directly applies to this and this signal starts on bit 0 and spans all the way to bit 9.

               <--------- byte 2 ---------->   <--------- byte 1 ---------->   <--------- byte 0 ---------->
               7   6   5   4   3   2   1   0    7   6   5   4   3   2   1   0   7   6   5   4   3   2   1   0
u64 offset =  23  22  21  20  19  18  17  16   15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0

Big Endian Examples

Big endian bits are not what they appear to be if you design the DBC manually. It is relatively difficult to design a big endian DBC without a UI based editor. Let us consider some examples:

Example 1

 SG_ BIG_ENDIAN1_16bit_msb_b0 : 0|16@0+ (1,0) [0|0] "" DBG

The signal that appears to start at b0 actually ends at b0. The first zero in 0|16@ means that the 16-bit Motorolla formatted signal has its MSB at b0. Have a look at where this signal really fits:

      bit  - 7   6   5   4   3   2   1   0
      ---- +---+---+---+---+---+---+---+---+
         0 |   |   |   |   |   |   |   |<--|
         1 |-------------------------------|
         2 |--------------------------*|   |
         | +---+---+---+---+---+---+---+---+
      byte |

To make sense of this, you have to re-arrange the bytes as Big Endian to form a contiguous signal. The key is to re-arrange the bytes from byte 0 to byte 2 starting from the left-hand side and spanning the right-hand side. Now, if you track this 16-bit signal that starts at bit 1 of byte 2 and go backwards, then you will find the range which ends at b0 of byte 0.

             <--------- byte 0 ---------->   <--------- byte 1 ---------->   <--------- byte 2 ---------->
               7   6   5   4   3   2   1   0    7   6   5   4   3   2   1   0   7   6   5   4   3   2   1   0
u64 offset =  63  62  61  60  59  58  57  56   55  54  53  52  51  50  49  48  47  46  45  44  43  42  41  40
            |   |   |   |   |   |   |   |<-m|---|---|---|---|---|---|---|---|---|---|---|---|---|---|-l*|   |

The formula to find the span of this signal is:

  • Span the signal from the next byte from high order bit to lower order bit (MSB is left, LSB is right)

  • Ending (MSB):

    • msb means most significant bit defined by DBC at 0|16 where msb = 0 in this case

    • Q = msb // 8 (integer division)

    • ((7 - Q) * 8) + msb - (Q * 8)

    • ((7 - 0) * 8) + 0 - (0 * 8)

    • 56 + 0 - 0 = 56

  • Starting (LSB):

    • end - length + 1

    • 56 - 16 + 1 = 41

Example 2

 SG_ BIG_ENDIAN2_16bit : 12|16@0+ (1,0) [0|0] "" DBG

The signal layout is:


             7   6   5   4   3   2   1   0
         0 |   |   |   |   |   |   |   |   |
         1 |   |   |   |<------------------|
         2 |-------------------------------|
     B   3 |----------x|   |   |   |   |   |
     y     +---+---+---+---+---+---+---+---+
     t               +-- BIG_ENDIAN2_16bit_msb_b4
     e     +---+---+---+---+---+---+---+---+

Because this is a Big Endian signal, we re-arrange the bytes into a uint64_t by placing byte 0 on the upper bits, and by placing byte 7 on the lower bits of the uint64_t. We have to do it this way because we want to get a contiguous signal that we can extract in a C program or equivalent.

Signal Overlay (byte 0 is omitted):

             <--------- byte 1 ---------->   <--------- byte 2 ---------->   <--------- byte 3 ---------->
             7   6   5   4   3   2   1   0   7   6   5   4   3   2   1   0   7   6   5   4   3   2   1   0
u64 offset   55  54  53  52  51  50  49  48  47  46  45  44  43  42  41  40  39  38  37  36  35  34  33  32
           |   |   |   |<-msb--------------|-------------------------------|------lsb-*|   |   |   |   |   |
  • Ending (MSB):

    • msb means most significant bit defined by DBC at 12|16 where msb = 12 in this case

    • Q = msb // 8 (integer division), so Q = 1

    • ((7 - Q) * 8) + msb - (Q * 8)

    • ((7 - 1) * 8) + 12 - (1 * 8)

    • 48 + 12 - 8 = 52

  • Starting (LSB):

    • end - length + 1

    • 52 - 16 + 1 = 37

Multiplexed Signals


  • Enumeration is a user defined data type. It is primarily used to assign labels to constants to make the logic easy to comprehend and maintain. Enumerated data types are data types consisting of a collection of values called enumerators. These values are comparable, but interpreters and compilers represent them arbitrarily, i.e., they do not have any specific representation in the memory. A variable that has been declared as having an enumerated type can have any of the enumerators as its value.

  • Particularly, in a DBC file format, the user utilizes enumeration to be able to use names instead of numbers to represent states. For example, in a traffic light state machine- the states '0', '1', '2' can be represented as "Red", "Yellow", and "Green" respectively. This can be achieved by adding the following two lines of code in the DBC file.

    • A "BA_" field is required, and you can follow the example below to list an enumeration as a "FieldType" first for the sake of simplicity.

    • A "VAL_" field is required to define the enumeration values.

BO_ 500 IO_DEBUG: 4 IO
 SG_ IO_DEBUG_test_enum : 8|8@1+ (1,0) [0|0] "" DBG

BA_ "FieldType" SG_ 500 IO_DEBUG_test_enum "Traffic_light";

VAL_ 500 IO_DEBUG_test_enum 0 "Red" 1 "Yellow" 2 "Green";


Cycle time, initial values etc

Typical CAN Driver

CAN Frame Structure

Bitrate Settings

A single bit is broken out into these separate time segments:

                    Nominal Bit Time (of one Bit) composed of 8 Tq
______________  _______________________________________________________  _________   
              \/      |      |                           |             \/   
 previous bit || SYNC | PROP |        PHASE SEG 1        | PHASE SEG 2 || next bit
               |                                         ^             |
               |                           Sample Point  | At 75%      |
                          (Time Quanta Tq)            (6) (2)  
  • Sync

    • During the Sync segment, we expect a bit edge transition

    • The Sync segment is always 1 Time Quanta (Tq)

  • Prop

    • The Propagation segment is used to compensate for delays in the bus lines

    • The Propagation segment is always a fixed length Tq

  • Phase & Phase 2

    • May be shortened or lengthened to help keep the clocks in sync

    • The Sample Point takes place between these 2 segments

Sample Point

The sample point is the point where bus levels are sampled. This always takes place between Phase 1 and Phase 2 segments. A sample point of 75% is a common starting point, but busses with high baud rate may require a later sample point.

You should configure the clock prescaler driving your CAN peripheral, and your segment Tq registers such that you can achieve your desired sample point. To make this easier, there are many tools online to do these calculations:

Bit Timing Calculator


The CAN controller will lengthen or shorten a bit by a maximum number known as Synchronization Jump Width. The integer value of SJW represents Tq. This is typically fine left at default value.


Hardware Filters

Filtering is a way to choose which messages to intercept from the CAN bus. The biggest confusion here is that as soon as your CAN is initialized, it will automatically ACK the frames for ALL frames. So just because you do not intercept a frame does not mean your CAN peripheral will not acknowledge.

Listen-only mode

End-to-End Example

Refer to this link

CAN Tools


Bus Master




Cantools is an awesome Python tool with so many features such as:

  • Parse DBC

  • Generate encode and decode functions

  • And much more

We used it to generate the signal overlay of the CAN bytes, using the command cantools dump your.dbc. It is very well written and highly recommended than writing your own DBC parser.

Bit Time Calculation

This article can be used to calculate the baud-rate register settings for various different CAN peripherals.

  • No labels