A CAN driver for the ESP32

Last year I ordered an ESP32, a chip that got quiet a lot of attention because it is small, affordable and comes with a free SDK. I worked with the predecessor, the ESP8266 and I think that the ESP32 is way easier to use and the SDK (called ESP-IDF) is much more powerful compared with the ESP8266.

Time to get hands on the ESP32 as I want a CAN/CANopen-Wifi bridge. The first few months nothing happend and I already thought that the chip will never arrive but finally I got mail from China. I started with a simple "Hello world" but soon found that there is no CAN driver included in the SDK. After some research I found that there is a CAN port and that the CAN module on the ESP32 is SJA1000 compatible.I stripped the driver to work out of the box with the latest SDK version. The code is not perfect (some magic numbers etc.) but should be a good starting point for an own driver.

As I do not want to go to jail because you build something with the code and someone dies:

This software is a PROTOTYPE version and is not designed or intended for use in production, especially not for safety-critical applications! The user represents and warrants that it will NOT use or redistribute the Software for such purposes. This prototype is for research purposes only. This software is provided "AS IS," without a warranty of any kind.


First we need the API definition for CAN:




Register definition


Module Initialization


Interrupt Service Routine (for all interrupts)


Read a Frame from the FIFO


Writing a CAN frame


Stop CAN Module


An example project can be downloaded here:



20 thoughts on “A CAN driver for the ESP32

  1. pallyya

    hi, you had done a very interesting work.
    im interested in developing a can driver for ESP32 and your work is very promising and well coded.
    can i use your code in my academic project and can you send me or post an example.
    thank you in advance.

  2. Pawel Szabaciuk

    "If you need the Code as a example project, post a comment."
    I would like some example if it is not a problem 🙂

  3. Hey guys,

    sorry for the late reply, I just have seen your posts. I will prepare an example project next week, including the latest version of the driver (dynamic baudrate calculation), based on the latest ESP-IDF. Of course you can use the code in your projects but plase not that there is absolutely no warrenty and it comes "AS IS".


    • Pawel Szabaciuk

      Thank you very much!

    • pallyya

      thank you very much, i will try as soon as possible.
      very good work

  4. Pawel Szabaciuk

    Hello again.
    Can you tell me if I need config anything to receive CAN2.0B extended frames?
    I've changed already CAN_read_frame function. I'am using MODULE_CAN->MBX_CTRL.FCTRL.FIR.B.FF flag to assembly message using MODULE_CAN->MBX_CTRL.FCTRL.TX_RX.EXT.
    But I don't get any message. I've been testing CAN2.0A standard frames at 500kbit and it is working correctly. But other device use 2.0B extended frames at 250kbit and I don't get any message.
    Can you have any idea what can I check?

    • So you don't receive any interrupts?
      I have not tried extended frames but my assumption is that the the acceptance filter is blocking them.
      I am afraid you have to check the SJA1000 manual and look where the acceptance filter for extended frames is configured. I guess its within the reserved field of ACC.

      • Pawel Szabaciuk

        I receive interrupts only with bus error. But it is normal, in working 500kbit also have some errors after start. I'll try with acceptance filter. Thank you!

        • Pawel Szabaciuk

          Unfortunately, acceptance filter has correct setup (according to SJA1000 documentation).
          Have you any other idea what can be wrong? Maybe config bits for 250kbits? But I think I was reading than you have been trying this speed (esp32.com).

          • There is currently a pending pull request.
            I will try if I can test and merge it tomorrow, If not, I will have no access to a computer for the next weeks, so please test it on your own.

  5. […] Source: A CAN driver for the ESP32 – Barth Development […]

  6. […] Source: A CAN driver for the ESP32 – Barth Development […]

  7. EmbeddedGuy

    Hi, thnx for posting this code. I am in the process of building a CAN listener. After looking at your code I've noticed that you are using pin GPIO5 and 6. Can it be set to any pins or are there limitations to which pins can be used? I am aware that pins 35 to 39 can only be used as inputs.

    • Hi,

      it depends on the board you are using. Depending on the board, some pins might be already in use. I am not aware of limitations in the GPIO matrix but also haven't digged too deep into this topic. Maybe simply start with proven in use pins, check if your setup is working and then move to your desired pins.

  8. jithesh v

    Hi ,
    I tried to build your sample project on esp-idf . but its showing the following errors.

    CC build/mbedtls/library/havege.o
    /bin/sh: //main.d: Is a directory
    make[1]: *** [/home/USER/esp-idf/make/component_wrapper.mk:275: //main.o] Error 1
    make: *** [C:/msys32/home/USER/esp-idf/make/project.mk:450: component-main-build] Error 2
    make: *** Waiting for unfinished jobs....

    please help..

  9. Swap

    Hi Thomas,

    Thanks for the wonderful work.

    Quick question: Can you confirm if the SJA1000 can be connected to the car's OBD II port or not? If not, where do we need to connect it in the car ?


    • You would need an additional CAN Transceiver like the MCP2551. If you can see something depends on if the manufacturer has routed a "interesting" CAN Network to the connector and if the network only speaks classical CAN.

      Please be aware that connecting a normal CAN device to CAN-FD Networks can cause problems. For this reason and many others, be very careful when messing with a car.

Leave a Reply

About Thomas Barth

Thomas Barth, born 1986, is a german teaching fellow and Ph.D. student. He studied electrical engineering in Darmstadt, Frankfurt and Helsinki and worked 7 years in industry automation before he switched to embedded systems and microelectronics. To read more about him, click here.