Skip to content

CAN Bus

The board uses a TJA1051T/3 CAN transceiver to provide CAN 2.0 and CAN FD tolerant (ISO 11898-2:2016) connectivity. The “/3” suffix denotes the V_IO variant, which provides level-shifted TXD and RXD logic pins that directly match the ESP32-S3’s 3.3V GPIO levels without requiring an external level shifter. The ESP32-S3 includes a built-in TWAI (Two-Wire Automotive Interface) peripheral that handles the CAN protocol in hardware, including arbitration, error detection, and automatic retransmission. The TJA1051T/3 provides the physical layer, translating between the microcontroller’s logic-level signals and the differential CAN bus signaling. The interface is exposed on a 3-pin screw terminal carrying CANH, CANL, and GND.

CAN bus was designed by Bosch in the 1980s for automotive wiring harnesses, and its fundamental properties — deterministic arbitration, built-in error handling, and multi-master architecture — have made it the backbone of automotive, industrial, and robotics communication ever since.

SignalGPIODescription
CAN TXIO15TWAI TX to TJA1051T
CAN RXIO16TWAI RX from TJA1051T

Connect CANH to CANH and CANL to CANL between nodes. CAN bus requires 120 ohm termination at both physical ends of the bus. The board includes an onboard 120 ohm termination resistor with jumper selection at position 19 (default: OFF). Place the jumper cap to enable termination.

The CAN bus lines are protected by SM24CANB TVS diodes, providing protection against surge events and ESD discharge on the bus wiring.

The TJA1051T/3 is an AEC-Q100 qualified CAN transceiver from NXP, designed for automotive and industrial applications where reliability under extreme conditions is non-negotiable.

ParameterValue
Part numberTJA1051T/3/1J
StandardISO 11898-2:2016 (CAN FD tolerant)
QualificationAEC-Q100 Grade 1 (-40 to +125 C)
Supply voltage (VCC)4.5V to 5.5V
I/O level voltage (V_IO)1.8V to 5.5V
Data rateUp to 5 Mbit/s (CAN FD)
Bus pin voltage tolerance-58V to +58V
Loop delay (TXD to RXD)200 ns typical
Dominant timeout2.5 ms to 7 ms
Operating modesNormal, Silent
Standby current< 10 uA

The V_IO pin is what distinguishes the “/3” variant from the base TJA1051T. The base part requires 5V logic levels on TXD and RXD, which would necessitate a level shifter between the transceiver and the ESP32-S3’s 3.3V GPIOs. The “/3” variant accepts a separate V_IO supply (1.8V to 5.5V) that sets the logic-level reference for TXD and RXD. On this board, V_IO is connected to 3.3V, allowing direct connection to the ESP32-S3 without any additional circuitry.

The TJA1051T/3 supports two operating modes, selected by the S (silent) pin:

  • Normal mode: S pin held LOW (connected to GND on this board). Both the transmitter and receiver are active, allowing the node to send and receive frames and participate fully in bus arbitration and acknowledgment. This is the default configuration.
  • Silent mode: S pin held HIGH. The receiver remains active but the transmitter is disabled — the transceiver cannot drive the bus. This mode is useful for bus monitoring and sniffing applications where the node should observe traffic without participating in arbitration or acknowledging frames. A node in silent mode is invisible to other bus participants.

On this board, the S pin is tied to GND, permanently selecting Normal mode. To use Silent mode, the S pin trace would need to be cut and routed to a GPIO for software control.

The TJA1051T/3 incorporates several protection mechanisms that make it suitable for safety-critical applications in automotive and industrial environments:

  • TXD dominant timeout: If TXD is held dominant (LOW) for longer than 2.5 to 7 ms, the transceiver automatically releases the bus to recessive state. This prevents a single faulting node — whether due to a software hang, latch-up, or oscillator failure — from blocking all communication on the bus. In a network of dozens of ECUs, one stuck transmitter would otherwise silence every other node.
  • Undervoltage detection: The transceiver monitors VCC and disables its output driver if the supply drops below the undervoltage lockout threshold. This prevents malformed or indeterminate bus signals during power-up, brown-out, or supply transient events that could corrupt frames in transit.
  • Thermal protection: An internal thermal shutdown circuit disables the transmitter if the die temperature exceeds safe operating limits, protecting both the transceiver and the bus from damage during sustained fault conditions.
  • Bus pin protection: Both CANH and CANL pins tolerate voltages from -58V to +58V, providing robust protection against wiring faults, ground offset between nodes, and transient events in electrically harsh environments such as automotive wiring harnesses and industrial machinery.
Bit RateMax Bus LengthESP-IDF Timing Macro
125 kbit/s500 mTWAI_TIMING_CONFIG_125KBITS()
250 kbit/s250 mTWAI_TIMING_CONFIG_250KBITS()
500 kbit/s100 mTWAI_TIMING_CONFIG_500KBITS()
1 Mbit/s25 mTWAI_TIMING_CONFIG_1MBITS()

The relationship between bit rate and maximum bus length is governed by the propagation delay of the electrical signal along the cable and the requirement that all nodes sample each bit at the same point in time. Higher bit rates demand shorter cables.

This example initializes the TWAI peripheral at 500 kbit/s and sends a standard CAN frame with ID 0x123 every second.

#include "driver/twai.h"
#define CAN_TX_PIN 15
#define CAN_RX_PIN 16
void setup() {
Serial.begin(115200);
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(
(gpio_num_t)CAN_TX_PIN, (gpio_num_t)CAN_RX_PIN, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
Serial.println("TWAI driver installed");
}
twai_start();
}
void loop() {
twai_message_t msg = {
.identifier = 0x123,
.data_length_code = 8,
.data = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
};
if (twai_transmit(&msg, pdMS_TO_TICKS(1000)) == ESP_OK) {
Serial.println("Message sent");
} else {
Serial.println("Send failed");
}
delay(1000);
}

Bus-Off Recovery

If the TWAI peripheral enters the bus-off state (too many errors), call twai_initiate_recovery() followed by twai_start() to bring it back online. Common causes include incorrect bit rate, missing termination, or wiring faults.

Message Filtering

The TWAI_FILTER_CONFIG_ACCEPT_ALL() macro accepts every frame on the bus. For production systems, configure acceptance filters to reduce interrupt load by only accepting message IDs your node cares about.