esp32开发与应用(升级到2.8寸屏幕)
·
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
前面我们学习了lvgl,也学习了怎么用lvgl写一个定时器。但是由于之前的屏幕分辨率不高,所以我们想调整一下,变成320*240。但这个时候,驱动芯片也发生了变化。之前是st7789,现在是ili9341,但是因为有ai,整个过程不复杂。

1、连线基本不变
不管是哪个驱动ic,接线部分基本还是spi接线,只是线序可能有差别。其他都是一样的。所以这部分不用担心。
2、主动告诉ai,换了驱动ic
我们在让ai写驱动代码的时候,需要主动告诉它,当前新的驱动ic是什么,分辨率是多少,默认哪个是长、那个是宽,这些都是需要提前说好的。不然生成的代码有可能是错的。
3、间隙性确认ai的代码
ai生成的代码,不保证每一步都是对的。这个时候一方面,我们要对代码进行保存;另外一方面需要把代码发给ai,告诉它下一个功能在这个基础上修改。这样基本上可以减少很多无谓的沟通。
4、发送需求给ai
到这里,我们应该知道如何发送需求给ai了,即在当前st7789 demo的基础之上,替换成ili9341 ic,分辨率是240*320,demo需要旋转过来,改动尽量最小。不出意外,就可以拿到这样的代码,
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_timer.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "lvgl.h"
//================================================
// ILI9341 CONFIG
//================================================
#define ILI9341_SPI_HOST SPI2_HOST
#define ILI9341_SCLK_PIN 14
#define ILI9341_MOSI_PIN 13
#define ILI9341_CS_PIN 15
#define ILI9341_DC_PIN 2
#define ILI9341_RST_PIN 4
#define ILI9341_BL_PIN 12
#define ILI9341_WIDTH 320
#define ILI9341_HEIGHT 240
#define ILI9341_SWRESET 0x01
#define ILI9341_SLPOUT 0x11
#define ILI9341_NORON 0x13
#define ILI9341_INVOFF 0x20
#define ILI9341_DISPON 0x29
#define ILI9341_CASET 0x2A
#define ILI9341_RASET 0x2B
#define ILI9341_RAMWR 0x2C
#define ILI9341_COLMOD 0x3A
#define ILI9341_MADCTL 0x36
static spi_device_handle_t ili9341_spi;
static SemaphoreHandle_t lvgl_mutex;
static lv_obj_t *label_time;
static lv_obj_t *label_date;
//================================================
// SPI LOW LEVEL
//================================================
static void ili9341_send_cmd(uint8_t cmd)
{
gpio_set_level(ILI9341_DC_PIN, 0);
spi_transaction_t t = {
.length = 8,
.tx_buffer = &cmd
};
spi_device_transmit(ili9341_spi, &t);
}
static void ili9341_send_data(const uint8_t *data, size_t len)
{
gpio_set_level(ILI9341_DC_PIN, 1);
spi_transaction_t t = {
.length = len * 8,
.tx_buffer = data
};
spi_device_transmit(ili9341_spi, &t);
}
//================================================
// WINDOW
//================================================
static void ili9341_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
ili9341_send_cmd(ILI9341_CASET);
uint8_t ca[] = { x0 >> 8, x0 & 0xFF, x1 >> 8, x1 & 0xFF };
ili9341_send_data(ca, 4);
ili9341_send_cmd(ILI9341_RASET);
uint8_t ra[] = { y0 >> 8, y0 & 0xFF, y1 >> 8, y1 & 0xFF };
ili9341_send_data(ra, 4);
ili9341_send_cmd(ILI9341_RAMWR);
}
//================================================
// LCD INIT
//================================================
static void ili9341_init(void)
{
gpio_set_level(ILI9341_RST_PIN, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(ILI9341_RST_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(120));
ili9341_send_cmd(ILI9341_SWRESET);
vTaskDelay(pdMS_TO_TICKS(120));
ili9341_send_cmd(ILI9341_SLPOUT);
vTaskDelay(pdMS_TO_TICKS(120));
ili9341_send_cmd(ILI9341_COLMOD);
ili9341_send_data((uint8_t[]){0x55}, 1);
ili9341_send_cmd(ILI9341_MADCTL);
ili9341_send_data((uint8_t[]){0x28}, 1);
ili9341_send_cmd(ILI9341_DISPON);
gpio_set_level(ILI9341_BL_PIN, 1);
}
//================================================
// SPI INIT
//================================================
static void ili9341_spi_init(void)
{
gpio_config_t io = {
.pin_bit_mask =
(1ULL << ILI9341_DC_PIN) |
(1ULL << ILI9341_RST_PIN) |
(1ULL << ILI9341_BL_PIN),
.mode = GPIO_MODE_OUTPUT
};
gpio_config(&io);
spi_bus_config_t buscfg = {
.mosi_io_num = ILI9341_MOSI_PIN,
.miso_io_num = -1,
.sclk_io_num = ILI9341_SCLK_PIN,
.max_transfer_sz = ILI9341_WIDTH * ILI9341_HEIGHT * 2
};
spi_device_interface_config_t devcfg = {
.clock_speed_hz = 20 * 1000 * 1000,
.mode = 0,
.spics_io_num = ILI9341_CS_PIN,
.queue_size = 7
};
spi_bus_initialize(ILI9341_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
spi_bus_add_device(ILI9341_SPI_HOST, &devcfg, &ili9341_spi);
}
//================================================
// LVGL FLUSH
//================================================
static void ili9341_flush_cb(lv_disp_drv_t *drv,
const lv_area_t *area,
lv_color_t *color_map)
{
uint32_t w = area->x2 - area->x1 + 1;
uint32_t h = area->y2 - area->y1 + 1;
uint32_t pixels = w * h;
ili9341_set_window(area->x1, area->y1, area->x2, area->y2);
gpio_set_level(ILI9341_DC_PIN, 1);
spi_transaction_t t = {
.length = pixels * 16,
.tx_buffer = color_map
};
spi_device_transmit(ili9341_spi, &t);
lv_disp_flush_ready(drv);
}
//================================================
// UI
//================================================
static void create_ui(void)
{
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_white(), 0);
lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0);
label_time = lv_label_create(lv_scr_act());
lv_label_set_text(label_time, "00:00:00");
lv_obj_set_style_text_color(label_time,
lv_color_hex(0xff0000), // brg
0);
lv_obj_set_style_text_font(label_time,
&lv_font_montserrat_48,
0);
lv_obj_align(label_time, LV_ALIGN_CENTER, 0, -30);
label_date = lv_label_create(lv_scr_act());
lv_label_set_text(label_date, "2026-06-17");
lv_obj_set_style_text_color(label_date,
lv_color_hex(0x00ff00), // brg
0);
lv_obj_set_style_text_font(label_date,
&lv_font_montserrat_20,
0);
lv_obj_align(label_date, LV_ALIGN_CENTER, 0, 35);
}
//================================================
// LVGL TICK
//================================================
static void lv_tick_cb(void *arg)
{
lv_tick_inc(1);
}
//================================================
// CLOCK TASK
//================================================
static void clock_task(void *arg)
{
int h = 0, m = 0, s = 0;
char buf[32];
while (1)
{
vTaskDelay(pdMS_TO_TICKS(1000));
s++;
if (s >= 60) { s = 0; m++; }
if (m >= 60) { m = 0; h++; }
if (h >= 24) { h = 0; }
sprintf(buf, "%02d:%02d:%02d", h, m, s);
if (xSemaphoreTake(lvgl_mutex, portMAX_DELAY))
{
lv_label_set_text(label_time, buf);
xSemaphoreGive(lvgl_mutex);
}
}
}
//================================================
// MAIN
//================================================
void app_main(void)
{
printf("ILI9341 START\n");
lvgl_mutex = xSemaphoreCreateMutex();
ili9341_spi_init();
ili9341_init();
lv_init();
esp_timer_handle_t timer;
const esp_timer_create_args_t tick_args = {
.callback = lv_tick_cb,
.name = "lv_tick"
};
esp_timer_create(&tick_args, &timer);
esp_timer_start_periodic(timer, 1000);
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[ILI9341_WIDTH * 20];
static lv_color_t buf2[ILI9341_WIDTH * 20];
lv_disp_draw_buf_init(&draw_buf,
buf1,
buf2,
ILI9341_WIDTH * 20);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = ILI9341_WIDTH;
disp_drv.ver_res = ILI9341_HEIGHT;
disp_drv.flush_cb = ili9341_flush_cb;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
create_ui();
xTaskCreate(clock_task, "clock_task", 4096, NULL, 5, NULL);
while (1)
{
lv_timer_handler();
vTaskDelay(pdMS_TO_TICKS(5));
}
}
5、编译、测试和验证
这部分和之前流程差不多,先编译、再烧入和测试。代码功能差不多了,再去慢慢看细节。要是代码本身都不能编译和烧录,或者运行是错的,那就意义不大。
注:
有一些屏幕虽然小一点,比如是2.4寸屏,但是分辨率也是320*240。所以这份代码可以直接port过去使用,没有问题,只要屏幕驱动芯片也是ILI9341。
更多推荐

所有评论(0)