M5 Stamp C3 -> Asign hardware pins for SPI

  • Hello,

    I would appreciate if someone could help me set up the SPI on the hardware pins of the Stamp C3 to connect to a display with the ST7789 driver.

    According to the documentation: page 169 [https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#spi], the pins that can be assigned with the MUX IO directly are these, integrated into my initialization code.

    #include <Adafruit_GFX.h> // Core graphics library by Adafruit
    #include "Arduino_ST7789.h" // Hardware-specific library for ST7789 (with or without CS pin)

    #define TFT_MISO -1
    #define TFT_MOSI GPIO_NUM_7 //FSPID en pin fisico 13 de CPU ESP32-C3
    #define TFT_SCLK GPIO_NUM_6 //FSPICLK en pin fisico 12 de de CPU ESP32-C3
    #define TFT_CS GPIO_NUM_5 // Chip select control pin //FSPIWP en pin 10 de CPU ESP32-C3
    #define TFT_DC GPIO_NUM_4 // Data Command control pin (8 Bits TFT 1.54 Soldable) //FSPIHD en pin fisico 9 de CPU ESP32-C3
    //#define TFT_DC -1 // 9 bits TFT 1.54 Display con cable
    #define TFT_RST GPIO_NUM_0 // Reset pin (could connect to RST pin) //en pin fisico 4 de CPU ESP32-C3

    //You can use different type of hardware initialization
    //using hardware SPI (11, 13 on UNO; 51, 52 on MEGA; ICSP-4, ICSP-3 on DUE and etc)
    //Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST); //for display without CS pin
    Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_CS); //for display with CS pin
    //or you can use software SPI on all available pins (slow)
    //Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK); //for display without CS pin
    //Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin
    // Arduino_ST7789 tft = Arduino_ST7789(-1, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin and DC via 9bit SPI

    void setup(void)
    Serial.print("ST7789 TFT Test...");

    tft.init(240, 320);   //initialize a ST7789 chip, 240x240 pixels cambiar a (#define ST7789_240x240_YSTART 80) en Arduino_ST7789.h
    tft.setRotation(0);   //Posicion con cinta o cable por arriba.


    void loop()

    Thank you,

  • Hello @ferqtek

    please have a look at this example I found. It works for me using your GPIO defines like below:

    #define TFT_MISO -1
    #define TFT_MOSI GPIO_NUM_7
    #define TFT_SCLK GPIO_NUM_6
    #define TFT_CS   GPIO_NUM_5
    #define TFT_DC   GPIO_NUM_4
    #define TFT_RST  GPIO_NUM_0
    Adafruit_ST7789 tft_ST7789 = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

    Please note:

    • the example uses the original Adafruit ST7855 library (which also supports ST7789)
    • I used a 135x240 display for my test

    BTW: if I do not define sclk and mosi, the default GPIOs seem to be incorrect for ESP32C3 as I get this error in the debug console:

    ST7789 TFT Test...[   112][E][esp32-hal-gpio.c:102] __pinMode(): Invalid pin selected
    E (272) gpio: gpio_set_level(226): GPIO output gpio_num error


  • @felmue You can see that "//or you can use software SPI on all available pins (slow)". You example use this initialization "Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin".
    But I prefer to use hardware pins for faster performance, so you must use this initialization "Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_CS); //for display with CS pin".
    and it doesn't work.

    I will now the steps for initialization at this link "https://github.com/m5stack/M5GFX/blob/5342c2b4528260beddc62d5656717e80b8375554/src/M5GFX.cpp#L1221"

    Thank you,

  • Hello @ferqtek

    ok, I see. However it is stated here:

    When an SPI Host is set to 80 MHz or lower frequencies, routing SPI pins via the GPIO matrix will behave the same compared to routing them via IOMUX.

    What SPI bus frequency are you planning to use?

    It also states:

    If at least one signal is routed through the GPIO matrix, then all signals will be routed through it.

    which I read as: if no signal is routed through the GPIO matrix then it is using IOMUX (but I could be wrong about that).


  • Hello.

    The truth is, I don't know if it's working for only one line to be routed by the IOMUX. But the speed I have is 600KHz, and for drawing on a display properly, it should be higher (6MHz). I found something on Espressif's website but give me various errors...
    It seems like the best option I've found. If you could indicate why it's giving errors and if it could be a good path, I would appreciate it. Thank you.


    NOTE: I can't find any example on the web for this ESP32_C3 that works, and it's disappointing that M5Stack doesn't have examples for it when they've left the default pins unconnected to the outside.

    Best regards,

  • Hello @ferqtek

    "by the speed I have", e.g. 600 kHz. Is that what you measure?

    What exactly is giving you errors? Building the spi master example or running it on an ESP32C3?

    What do you mean M5Stack left the default pins unconnected to the outside? Do you mean the SPI default pins? As far as I can tell, GPIOs 4, 5, 6, 7 and 10 are the default SPI pins for ESP32C3 and they are all available on the M5StampC3. (MISO - GPIO2 is not available, but also not needed for driving an LCD.)

    BTW: I think you might make your life to hard. If a clock frequency of 6 MHz is what your looking for it doesn't matter whether you are using hardware or software SPI.


  • Hello Felix,

    After reviewing everything, I have discovered that the issue lies in the initialization performed in the Arduino_ST7789 library. In the Arduino_ST7789.cpp file, SPI.begin(); is used when to utilize hardware SPI, it should be initialized with SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, TFT_CS);

    "// Constructor when using hardware SPI. Faster, but must use SPI pins
    // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.)
    // Parece que solo vale para 4-wire. Adaptar a 3-wire.
    Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t cs)
    : Adafruit_GFX(ST7789_TFTWIDTH, ST7789_TFTHEIGHT) {
    _cs = cs;
    _dc = dc;
    _rst = rst;
    _SPI9bit = false;
    _sid = _sclk = -1;

    After call
    "// Initialization code common to all ST7789 displays
    void Arduino_ST7789::commonInit(const uint8_t *cmdList) {......."
    in this part into
    { // Using hardware SPI
    #if defined (SPI_HAS_TRANSACTION)
    mySPISettings = SPISettings(48000000, MSBFIRST, SPI_MODE2); // BY ME"

    Always in the file.ino define pins:
    #define TFT_MISO -1
    #define TFT_MOSI 7
    #define TFT_SCLK 6
    #define TFT_CS 5
    #define TFT_DC 4
    #define TFT_RST 0
    call with:
    "Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_CS); //for display with CS pin // <--- MODO SPI HARDARE (4-wire)"

    In summary... I think that It wasn't working because the SPI was not initialized with the pin parameters and Mode 2 (function 2 of the IO_MUX) that activates pins 4, 5, 6, 7 (see page 169 of the ESP32-C3 datasheet). In the schematic, it can be seen that M5stack associates the SPI with pins 19, 20, 21, 22, 23, 24 in Mode 0 (function 0 of the IO_MUX), which needs to be initialized correctly...

    For drawing text or lines, etc., using Software SPI isn't a problem. However, if images, fillscreen();, or other graphical elements are displayed, then Hardware SPI is necessary (not necesary 48Mhz, i put in the code), or else everything will be very slow on the screen.


    Schematic M5Stack Stamp C3:

    I am happy!! It works now!!.

    Thank you for your time and attention.
    Best regards,