开发板 【正点原子】DNESP32S3开发板
在这里插入图片描述
基于 ESP-IDF esp_lcd 驱动框架,驱动 ST7789 SPI 液晶屏(320*240),搭配 XL9555 I2C IO 扩展芯片控制 LCD 电源、硬件复位;支持两种显示模式:波纹动画特效 / 静态原图显示,采用双行缓冲 DMA 分片刷屏提升 SPI 传输效率。

SPI 总线初始化

spi_bus_config_t buscfg = {
    .sclk_io_num = EXAMPLE_PIN_NUM_PCLK,
    .mosi_io_num = EXAMPLE_PIN_NUM_DATA0,
    .miso_io_num = -1,          // 单向SPI,无读取,MISO不使用
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
    // 单次SPI最大传输长度:分片行数×宽度×2字节像素 + 头部预留
    .max_transfer_sz = PARALLEL_LINES * EXAMPLE_LCD_H_RES * 2 + 8
};
// 挂载SPI2总线,自动分配DMA通道
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));

创建 SPI-LCD IO 适配器

esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_spi_config_t io_config = {
    .dc_gpio_num = EXAMPLE_PIN_NUM_DC,
    .cs_gpio_num = EXAMPLE_PIN_NUM_CS,
    .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
    .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
    .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
    .spi_mode = 0,               // SPI模式0 CPOL=0 CPHA=0,ST7789标准
    .trans_queue_depth = 10,     // SPI异步传输队列深度,缓存多笔刷屏请求
};
// 绑定SPI总线生成IO句柄
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));

创建 ST7789 面板驱动 & 屏幕参数配置

esp_lcd_panel_dev_config_t panel_config = {
    .reset_gpio_num = EXAMPLE_PIN_NUM_RST, // 无直连复位脚,填NC
    .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // 像素色彩顺序RGB
    .bits_per_pixel = 16,                   // RGB565 16bit色深
};
// 实例化ST7789厂商驱动,生成全局panel_handle
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
// 执行ST7789寄存器初始化(发送初始化指令序列)
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
// 打开屏幕显示输出
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); // 反转颜色(适配屏幕底色)
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));      // 交换XY轴(旋转90度)
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false));// X轴镜像,Y轴不镜像

图片显示函数

extern uint16_t *pixels; // 外部全局原图缓冲区(外部文件定义的全屏RGB565图像)
    for (int y = 0; y < EXAMPLE_LCD_V_RES; y += PARALLEL_LINES)
    {
        uint16_t *dst = s_lines[calc_line]; // 目标DMA缓冲
        // 遍历分片内每一行
        for (int yy = 0; yy < PARALLEL_LINES; yy++)
        {
            int real_y = y + yy;
            // 拷贝单行所有像素到DMA缓冲
            for (int x = 0; x < EXAMPLE_LCD_H_RES; x++)
            {
                *dst++ = pixels[real_y * EXAMPLE_LCD_H_RES + x];
            }
        }
        sending_line = calc_line;
        calc_line = !calc_line;
        esp_lcd_panel_draw_bitmap(panel_handle, 0, y, EXAMPLE_LCD_H_RES, y + PARALLEL_LINES, s_lines[sending_line]);
    }

更多推荐