Skip to content

Instantly share code, notes, and snippets.

@CodeZombie
Last active January 24, 2026 06:10
Show Gist options
  • Select an option

  • Save CodeZombie/385ad82980c6f7b5c169ee7d86185a37 to your computer and use it in GitHub Desktop.

Select an option

Save CodeZombie/385ad82980c6f7b5c169ee7d86185a37 to your computer and use it in GitHub Desktop.
esp_lcd ili9341 initialization
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_ili9341.h"
#define SPI_HOST SPI2_HOST // FSPI on S2
esp_lcd_panel_handle_t panel_handle;
void initialize_ili9341() {
spi_bus_config_t buscfg = {
.miso_io_num = -1,
.mosi_io_num = PIN_MOSI,
.sclk_io_num = PIN_SCK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = SCREEN_WIDTH * 10 * sizeof(uint16_t)
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = PIN_DC,
.cs_gpio_num = PIN_CS,
.pclk_hz = 40 * 1000 * 1000, // 40MHz
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.spi_mode = 0,
.trans_queue_depth = 10,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI_HOST, &io_config, &io_handle));
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = PIN_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(io_handle, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, false));
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
}
@CodeZombie
Copy link
Author

Leaving this here in case it's useful for someone in the future.
There only seems to be one example of the ili9341 startup routine using ESP-IDF's ESP_LCD library anywhere online, and it's very hard to read. Here's a real simple example.

After you get this working, you can blit to the screen with

esp_lcd_panel_draw_bitmap(panel_handle, x, y, x + w, y + h, color_buffer);

@CodeZombie
Copy link
Author

I think the ESP_LCD library sets up DMA for you in the background, so I don't think there's much SPI polling going on (beyond the necessary PASET and CASET, which what minimal docs exist claim are done via polling), but I haven't actually confirmed that the pixel transfer is done via DMA, but it appears that that is the case.

@CodeZombie
Copy link
Author

CodeZombie commented Jan 24, 2026

Okay, yeah link confirms that cmds are sent via polling, so that confirms that this library isn't doing any more hardware acceleration beyond what you could already accomplish with the standard esp SPI library. So if you use this, you're just paying for the library's overhead for no gain.

I'd recommend just setting the driver up manually and handling DMA yourself. I care deeply about optimization with microcontroller display drivers, and using ESP_LCD just makes optimization harder.
plus it does runtime checks on your esp_lcd_panel_draw_bitmap calls (checks to see if start_x is less than end_x, etc) so that's just unnecessary overhead for nothin'. You should be ensuring that situation can't happen before you even think about sending a buffer to SPI, so that's really an unnecessary couple of cycles for no gain (unless you're writing bad code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment