1. 基于ESP32-S3的1.9寸ST7789V3彩屏SPI驱动移植与实战
基于ESP32-S3的1.9寸ST7789V3彩屏SPI驱动移植与实战最近在ESP32-S3上折腾一个小屏幕发现这块1.9寸的ST7789V3彩屏性价比挺高显示效果也不错但网上的驱动资料比较零散。我花了不少时间把软件SPI和硬件SPI两种驱动方式都调通了今天就把完整的移植过程分享出来手把手教你怎么让这块屏幕在ESP32-S3上亮起来。这篇教程适合正在用ESP32-S3做显示项目的朋友无论你是刚入门还是有一定经验的开发者都能跟着步骤完成。咱们会从硬件接线开始讲到驱动代码的获取和集成最后用实际代码验证显示效果。过程中我会分享一些调试时踩过的坑帮你少走弯路。1. 屏幕与硬件准备1.1 屏幕规格与资料获取咱们用的这块是1.9寸的彩色LCD屏幕驱动芯片是ST7789V3。先来看看它的基本参数参数规格工作电压3.3V工作电流约50mA模块尺寸29mm (高) x 62mm (宽)显示分辨率170 (水平) x 320 (垂直) RGB通信协议SPI (支持软件SPI和硬件SPI)引脚数量8 Pin (2.54mm间距排针)屏幕的采购链接和资料包我都放在这里方便你获取采购链接淘宝商品链接资料下载链接: https://pan.baidu.com/s/1ArmQST7I84UYY7n0aJdEBw 提取码: 8888资料包里包含了完整的驱动代码、示例程序和一些文档是咱们后续移植的基础。1.2 通信原理SPI简介这块屏幕通过SPI接口和ESP32-S3通信。SPI是一种高速、全双工的同步通信协议简单理解就是主设备MCU和从设备屏幕之间用几根线来“对话”。SCK (SCL)时钟线由主设备产生像打拍子一样同步数据收发。MOSI (SDA)主设备输出、从设备输入线主设备通过这根线发送数据给屏幕。CS片选线当主设备要和某个从设备通信时就把对应从设备的这根线拉低选中它。其他引脚除了上述SPI必需的引脚屏幕还有DC数据/命令选择、RES复位、BLK背光控制等控制引脚。ESP32-S3芯片内部集成了多个SPI控制器SPI0 SPI1主要预留给内部访问外部Flash和PSRAM我们一般不用。SPI2 (GP-SPI2) SPI3 (GP-SPI3)这两个是通用的SPI控制器我们可以自由使用也就是常说的“硬件SPI”。“软件SPI”则是用普通的GPIO引脚通过程序模拟SPI的时序来通信好处是引脚选择灵活但速度比硬件SPI慢。2. 硬件连接引脚接线图接线是第一步也是最容易出错的一步。屏幕有8个引脚我们需要根据选择的通信方式软件SPI或硬件SPI连接到ESP32-S3对应的GPIO上。2.1 软件SPI接线软件SPI不挑剔引脚你可以选择ESP32-S3上任意空闲的GPIO。下面是我推荐的一组引脚连接比较常用表2.1-1 1.9寸屏引脚说明屏幕引脚标号引脚名称功能说明1GND电源地2VCC电源正 (3.3V)3SCLSPI时钟线 (SCK)4SDASPI数据线 (MOSI)5RES复位引脚 (低电平有效)6DC数据/命令选择引脚7CS片选引脚 (低电平有效)8BLK背光控制 (高电平点亮)表2.1-2 软件SPI推荐接线方式ESP32-S3 GPIO连接至屏幕引脚备注GPIO2SCL (3)SPI时钟GPIO3SDA (4)SPI数据输出GPIO4RES (5)复位信号GPIO5DC (6)数据/命令选择GPIO6CS (7)片选信号GPIO7BLK (8)背光控制3.3VVCC (2)电源GNDGND (1)电源地注意如果你的项目GPIO紧张有两个引脚可以简化RES引脚可以接到ESP32-S3的复位引脚EN。这样开发板复位时屏幕也跟着复位省下一个GPIO。代价是无法通过软件单独复位屏幕。BLK引脚可以直接接到3.3V或悬空。接到3.3V则背光常亮悬空则背光不亮通常内部有弱上拉可能微亮。代价是失去了通过程序调节背光亮度的能力。2.2 硬件SPI接线硬件SPI需要连接到ESP32-S3指定的SPI功能引脚上这样才能发挥硬件加速的优势。这里我们以使用SPI2_HOST即GP-SPI2为例。表2.2-1 硬件SPI推荐接线方式 (使用SPI2)ESP32-S3 GPIO默认SPI2功能连接至屏幕引脚GPIO12SPI2_CLKSCL (3)GPIO11SPI2_MOSISDA (4)GPIO4(自定义GPIO)RES (5)GPIO5(自定义GPIO)DC (6)GPIO6(自定义GPIO)CS (7)GPIO7(自定义GPIO)BLK (8)可以看到对于硬件SPI只有时钟(SCK)和数据输出(MOSI)必须使用固定的功能引脚GPIO12和GPIO11。RES、DC、CS、BLK这些控制引脚依然可以像软件SPI一样自由分配普通GPIO。3. 驱动移植将代码集成到你的工程硬件接好线接下来就是把驱动代码“搬”到我们的ESP32-S3项目里。资料包里已经提供了写好的驱动我们只需要把它放到正确的位置并修改配置文件。3.1 获取驱动文件首先你需要从之前提供的资料下载链接中找到驱动文件包。根据原文指引文件位于资料下载中心 - 模块移植资料下载 - 该章节配套压缩包中。下载后解压你会找到一个名为LCD的文件夹。这个文件夹里就包含了驱动屏幕所需的所有源文件.c和.h。3.2 将驱动文件加入工程复制文件打开你的ESP-IDF项目将下载得到的整个LCD文件夹复制到你项目的main目录下。通常你的项目结构会像这样你的项目/ ├── CMakeLists.txt ├── main/ │ ├── CMakeLists.txt │ ├── main.c │ └── LCD/ -- 把文件夹复制到这里 │ ├── lcd_init.c │ ├── lcd_init.h │ ├── lcd.c │ └── ...修改编译配置为了让编译器知道这些新文件的存在需要修改main目录下的CMakeLists.txt文件。 用VS Code或其他编辑器打开main/CMakeLists.txt在idf_component_register部分添加LCD文件夹的路径。通常是在SRCS和INCLUDE_DIRS里添加。一个简单的修改示例如下idf_component_register(SRCS main.c LCD/lcd_init.c LCD/lcd.c # ... 添加其他LCD文件夹下的.c文件 INCLUDE_DIRS . LCD # 添加这一行让编译器能找到.h文件 )更规范的做法是使用aux_source_directory命令自动添加所有.c文件但手动列出更清晰也不容易出错。3.3 关键配置根据接线修改引脚定义驱动文件里有一个关键的头文件通常是lcd_init.h或lcd_conf.h里面定义了所有用到的GPIO引脚编号。你必须根据你实际的接线方式修改这里打开LCD/lcd_init.h文件找到类似下面的引脚定义部分// 软件SPI引脚定义示例 #define LCD_SCL_PIN 2 #define LCD_SDA_PIN 3 #define LCD_RES_PIN 4 #define LCD_DC_PIN 5 #define LCD_CS_PIN 6 #define LCD_BLK_PIN 7 // 或者硬件SPI引脚定义示例 #define LCD_SPI_HOST SPI2_HOST #define LCD_SCLK_PIN 12 #define LCD_MOSI_PIN 11 #define LCD_RES_PIN 4 #define LCD_DC_PIN 5 #define LCD_CS_PIN 6 #define LCD_BLK_PIN 7请务必将这些#define后面的数字改成你实际连接ESP32-S3的GPIO编号。如果你用的是硬件SPI还需要确认LCD_SPI_HOST与你使用的SPI控制器一致SPI2_HOST或SPI3_HOST。修改完引脚定义驱动移植的核心工作就完成了。4. 功能验证编写测试程序点亮屏幕代码集成好了引脚也配置对了是时候上电测试了。我们在主程序main.c里写一段简单的测试代码来验证屏幕是否正常工作。4.1 测试代码解析打开你的main/main.c文件将内容替换为以下测试代码。这段代码会初始化屏幕先清屏为白色然后循环显示一些文字、数字、图片和一个递增的浮点数。#include stdio.h #include inttypes.h #include sdkconfig.h #include freertos/FreeRTOS.h #include freertos/task.h #include esp_chip_info.h #include esp_flash.h #include esp_timer.h // 包含我们移植的LCD驱动头文件 #include LCD/lcd_init.h #include LCD/lcd.h #include LCD/pic.h // 包含图片数据 void app_main(void) { float t 0.0; // 用于演示的浮点数变量 LCD_Init(); // 第一步初始化LCD屏幕这是必须的 LCD_Fill(0, 0, LCD_W, LCD_H, WHITE); // 第二步用白色填充整个屏幕 while(1) { // 以下代码在循环中执行动态刷新显示内容 // 1. 显示中文 LCD_ShowChinese(40, 0, (uint8_t *)中电科, RED, WHITE, 32, 0); // 2. 显示字符串和屏幕宽度 LCD_ShowString(10, 33, (uint8_t *)LCD_W:, RED, WHITE, 32, 0); LCD_ShowIntNum(106, 33, LCD_W, 3, RED, WHITE, 32); // LCD_W是驱动里定义的屏幕宽度 // 3. 显示字符串和屏幕高度 LCD_ShowString(10, 66, (uint8_t *)LCD_H:, RED, WHITE, 32, 0); LCD_ShowIntNum(106, 66, LCD_H, 3, RED, WHITE, 32); // LCD_H是驱动里定义的屏幕高度 // 4. 显示一个不断增加的浮点数 LCD_ShowFloatNum1(10, 99, t, 4, RED, WHITE, 32); t 0.11; // 5. 在指定位置显示一张40x40像素的图片 // gImage_1 是 pic.h 中定义好的图片数组 LCD_ShowPicture(160, 95, 40, 40, gImage_1); // 延时1秒让变化看得清 delay_ms(1000); // 你可以尝试取消下面几行注释看看全屏刷色的效果 // LCD_Fill(0,0,LCD_W,LCD_H,RED); // delay_ms(500); // LCD_Fill(0,0,LCD_W,LCD_H,GREEN); // delay_ms(500); // LCD_Fill(0,0,LCD_W,LCD_H,BLUE); // delay_ms(500); // LCD_Fill(0,0,LCD_W,LCD_H,WHITE); // delay_ms(500); } }4.2 编译、烧录与上电编译工程在VS Code的ESP-IDF终端或你的项目目录下运行idf.py build命令编译项目。连接开发板用USB线将ESP32-S3开发板连接到电脑确保端口被系统识别。烧录程序运行idf.py -p PORT flash命令将程序烧录到开发板将PORT替换为你的实际串口号如COM3或/dev/ttyUSB0。上电观察烧录完成后程序会自动运行。观察你的1.9寸屏幕屏幕背光应该点亮。屏幕首先会全白。随后屏幕上会显示“中电科”三个红字以及屏幕的宽高参数应该是170和320。一个红色的浮点数会每秒增加0.11。屏幕右侧会显示一张内置的小图片。如果一切顺利恭喜你驱动移植成功如果屏幕没反应别着急可以按照下面的排查思路看看。5. 常见问题与调试心得搞嵌入式一次成功是幸运调试才是常态。这里分享几个我调试时遇到的问题和解决方法。屏幕完全无显示背光也不亮检查电源首先用万用表量一下屏幕VCC和GND引脚是不是3.3V。ESP32-S3的3.3V输出能力有限如果接了很多外设可能导致电压被拉低。检查背光确认BLK引脚是否接对了。如果接的是GPIO检查程序里是否将其设置为高电平输出如果直接接3.3V检查连接是否牢固。检查复位测量RES引脚正常工作时应该是高电平。可以在程序初始化前手动给一个低电平脉冲拉低再拉高来复位屏幕。屏幕背光亮但无任何内容白屏或花屏检查接线这是最常见的问题逐根线检查SCL、SDA、DC、CS是否与程序中的定义一一对应有没有虚焊或接错。特别是DC和CS引脚接反了肯定没显示。检查SPI模式ST7789V3通常使用SPI Mode 0或Mode 3。确保驱动代码里的SPI模式设置正确。资料包里的驱动一般是设置好的如果你用的其他驱动库需要留意。降低SPI速度尤其是软件SPI如果初始化速度太快屏幕可能反应不过来。尝试在初始化函数里在发送初始化命令序列前增加一个几十毫秒的延时vTaskDelay(pdMS_TO_TICKS(50))。显示内容错位、乱码或颜色不对检查屏幕扫描方向ST7789V3可以通过命令设置扫描方向Rotation。驱动里一般有LCD_Display_Dir之类的函数。如果你发现文字是横着的或者镜像的调用这个函数修改方向即可。检查颜色格式ESP32-S3和屏幕可能使用不同的颜色格式如RGB565、RGB888。确保驱动中颜色数据的发送格式与屏幕期望的格式一致。资料包里的驱动通常已适配好。硬件SPI不工作但软件SPI可以确认引脚复用确保你为硬件SPISCLK, MOSI分配的GPIO在ESP32-S3上确实具有SPI功能。参考ESP32-S3的技术手册或引脚定义图。检查SPI控制器初始化硬件SPI驱动中除了配置引脚还需要正确初始化SPI主机spi_bus_initialize和设备spi_device_interface_config_t。对比资料包里的硬件SPI驱动示例看是否有遗漏步骤。调试时逻辑分析仪或者示波器是神器可以抓取SPI总线上的波形看时钟和数据有没有正常发出。没有仪器的话就耐心点用“二分法”排查先确保电源和复位再确保SPI数据线最后看配置命令。好了关于ESP32-S3驱动1.9寸ST7789V3彩屏的教程就到这里。从硬件连接到软件移植再到调试上电整个过程走下来你应该对SPI屏的驱动有了更实在的理解。这套驱动代码框架比较清晰你完全可以在此基础上去实现更复杂的UI、动画或者图形菜单。