Proyek ESP-IDF dapat berhasil meng-include esp_lcd_panel_io.h, tetapi tetap gagal ketika memakai esp_lcd_i80_bus_config_t atau esp_lcd_new_i80_bus(). Sekilas keduanya terlihat bertentangan, sampai target build ikut diperiksa.
esp_lcd adalah framework, bukan jaminan bahwa setiap chip ESP menyediakan semua transport LCD. SoC yang dipilih menentukan interface level rendah mana yang ikut dikompilasi. Dukungan controller panel seperti ILI9341 berada di lapisan lain lagi.
Perbedaan ini penting ketika kode dipindahkan dari satu varian ESP32 ke varian lainnya.
Error compiler sering menunjukkan batas kemampuan hardware
Kegagalan yang umum terlihat seperti ini:
error: unknown type name 'esp_lcd_i80_bus_config_t'
error: implicit declaration of function 'esp_lcd_new_i80_bus'
error: unknown type name 'esp_lcd_panel_io_i80_config_t'
error: implicit declaration of function 'esp_lcd_new_panel_io_i80'Petunjuk pertama yang berguna bukan baris source code, melainkan perintah compiler di sekitarnya.
Sebagai contoh, path seperti:
components/esp_hw_support/port/esp32c6/
components/hal/esp32c6/menunjukkan bahwa CMake mengonfigurasi proyek untuk ESP32-C6. Source code yang sama dapat memperoleh kumpulan interface LCD berbeda ketika dikonfigurasi untuk target lain.
ESP-IDF mendeskripsikan dukungan hardware melalui macro kapabilitas SoC. Target dengan dukungan native Intel 8080 LCD mengekspos jalur native I80; target tanpa kapabilitas tersebut tidak otomatis mendapatkannya hanya karena header generik esp_lcd tersedia.
Gunakan header khusus transport
Ada masalah kedua yang dapat menghasilkan error serupa: hanya meng-include header panel generik.
API native I80 memiliki header sendiri:
#include "esp_lcd_io_i80.h"
#include "esp_lcd_panel_ops.h"Header tersebut mendeklarasikan konfigurasi bus native I80 dan fungsi seperti:
esp_lcd_i80_bus_config_t
esp_lcd_new_i80_bus()
esp_lcd_panel_io_i80_config_t
esp_lcd_new_panel_io_i80()Namun include yang benar tidak menghapus batas SoC. Dua syarat harus terpenuhi sekaligus: kode harus meng-include header API yang sesuai dan target yang dipilih harus mendukung API tersebut.
Karena itu, menambahkan include directory secara manual bukan solusi yang tepat. Jika sebuah deklarasi memang dikecualikan untuk target tertentu, memaksa path header hanya akan memindahkan kegagalan ke bagian lain.
Driver panel dan transport adalah dua lapisan berbeda
ILI9341 menambah satu sumber kebingungan yang cukup umum.
Komponen esp_lcd merupakan bagian dari ESP-IDF. Komponen ini menyediakan abstraksi panel umum dan implementasi transport yang didukung. Ia tidak diinstal dari ESP Component Registry dengan nama espressif/esp_lcd.
Driver controller ILI9341 didistribusikan terpisah sebagai komponen espressif/esp_lcd_ili9341. Proyek dapat menambahkannya melalui Component Manager:
idf.py add-dependency "espressif/esp_lcd_ili9341"Aplikasi kemudian meng-include header drivernya:
#include "esp_lcd_ili9341.h"Header inilah yang menyediakan esp_lcd_new_panel_ili9341().
Arsitekturnya lebih mudah dibaca sebagai tiga lapisan:
application / LVGL
|
v
ILI9341 panel driver
|
v
panel IO transport
(SPI, native I80, atau transport lain yang didukung)
|
v
ESP SoC peripheralMenginstal komponen ILI9341 menyelesaikan deklarasi driver panel yang hilang. Langkah itu tidak menciptakan peripheral native I80 pada chip yang memang tidak memilikinya.
Native I80 bukan satu-satunya cara menggerakkan panel I80
Pada chip dengan dukungan native I80, ESP-IDF memakai esp_lcd_new_i80_bus() lalu esp_lcd_new_panel_io_i80(). Bus dapat menggunakan 8 atau 16 jalur data, kemudian panel IO membawa command dan data pixel ke controller.
Konfigurasi bus minimal berbentuk seperti ini:
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = PIN_DC,
.wr_gpio_num = PIN_WR,
.data_gpio_nums = {
PIN_D0, PIN_D1, PIN_D2, PIN_D3,
PIN_D4, PIN_D5, PIN_D6, PIN_D7,
},
.bus_width = 8,
.max_transfer_bytes = 240 * 40 * sizeof(uint16_t),
};Memakai LCD_CLK_SRC_DEFAULT lebih aman daripada menyalin konstanta clock source dari contoh untuk SoC lain. Pilihan clock source juga bergantung pada target.
Sebagian chip ESP yang lebih baru tanpa peripheral LCD I80 native memiliki peripheral Parallel IO. Dokumentasi ESP-IDF saat ini menjelaskan transport Parlio pada esp_lcd yang dapat mensimulasikan interface I80 8-bit pada target yang didukung. API-nya berbeda:
#include "esp_lcd_io_parl.h"
esp_lcd_panel_io_parl_config_t io_config = {
.dc_gpio_num = PIN_DC,
.clk_gpio_num = PIN_WR,
.cs_gpio_num = PIN_CS,
.data_gpio_nums = {
PIN_D0, PIN_D1, PIN_D2, PIN_D3,
PIN_D4, PIN_D5, PIN_D6, PIN_D7,
},
.data_width = 8,
.pclk_hz = 10 * 1000 * 1000,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
};Ini bukan API yang sama dengan native I80. Kode yang dibangun di sekitar esp_lcd_i80_bus_config_t tidak menjadi portabel ke target yang hanya menggunakan Parlio hanya dengan mengganti nomor GPIO.
Versi ESP-IDF juga berpengaruh karena dukungan transport terus berkembang. Periksa dokumentasi untuk target dan release IDF yang benar-benar digunakan proyek, bukan menganggap contoh ESP32-S3 otomatis berlaku pada ESP32-C6.
Target build harus diperiksa sebelum mapping pin
Mapping GPIO biasanya dibahas lebih dulu pada display paralel karena bus 8-bit memakai banyak pin. Dalam praktiknya, pemilihan target seharusnya dilakukan lebih dulu.
Periksa secara eksplisit:
idf.py set-target esp32s3atau:
idf.py set-target esp32c6Kemudian build ulang dari target yang sudah dikonfigurasi:
idf.py reconfigure
idf.py buildDi VS Code, extension ESP-IDF melakukan konfigurasi target yang sama melalui perintah pemilihan target. Perintah compiler yang dihasilkan tetap menjadi acuan terakhir: jika di sana tertulis esp32c6, proyek sedang dikompilasi sebagai ESP32-C6, terlepas dari development board yang sebenarnya ingin digunakan.
Setelah itu barulah D0-D7, WR, DC, CS, reset, dan backlight dipetakan ke GPIO.
LVGL berada di atas keputusan transport
LVGL tidak mensyaratkan native I80. Yang dibutuhkan adalah jalur flush display yang dapat mengirim buffer pixel hasil render ke panel.
Dengan esp_lcd, batas yang berguna biasanya berada di esp_lcd_panel_draw_bitmap(). Panel handle menyembunyikan urutan command khusus controller, sedangkan panel IO di bawahnya menentukan apakah byte dikirim melalui SPI, I80, atau interface lain yang didukung.
Pemisahan ini berarti UI LVGL sebaiknya tidak terikat langsung ke esp_lcd_new_i80_bus(). Tempatkan pembuatan bus dan inisialisasi panel di backend display, lalu berikan panel yang sudah siap ke port LVGL.
Dengan struktur itu, UI lebih mudah dipindahkan antara ESP32-S3 yang memakai native I80 dan target lain yang memakai SPI atau jalur Parlio yang didukung.
Baca deklarasi yang hilang dari lapisan terbawah
Ketika build LCD gagal, urutan pemeriksaan berikut menghemat banyak waktu:
- Pastikan target ESP-IDF yang sebenarnya dari output build.
- Periksa apakah SoC tersebut mendukung transport LCD yang ingin digunakan.
- Include header khusus transport, bukan hanya header panel generik.
- Bedakan framework bawaan
esp_lcddari komponen controller panel eksternal. - Tambahkan
espressif/esp_lcd_ili9341hanya ketika driver ILI9341 memang diperlukan. - Atur GPIO setelah transport dipastikan tersedia untuk target tersebut.
Dengan begitu, error unknown type name 'esp_lcd_i80_bus_config_t' justru memberi petunjuk yang cukup spesifik. Yang perlu diperiksa adalah batas antara kode LCD generik dan dukungan hardware target, bukan terus menambahkan include path sampai compiler berhenti mengeluh.