news 2026/9/23 1:44:30

ESP32驱动LCD屏实战:SPI与8080并口从接线到代码全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP32驱动LCD屏实战:SPI与8080并口从接线到代码全解析

玩ESP32的人迟早会碰到一块屏幕。

不管你是做温湿度计、桌面时钟、离线的仪表盘,还是想给蓝牙控制的小项目加一个可视化界面,LCD屏几乎是绕不开的组件。而网上关于ESP32驱动LCD的教程,要么只讲了某个屏的零散接线,要么一上来就扔给你一份库文件让你自己琢磨,真正能把SPI、8080并口、引脚选择、代码配置这些事讲清楚的反而很少。这篇文章想做的就是这样一件事:从最常用的SPI屏开始,再到速度更快的8080并口屏,把选型、接线、驱动配置、排错这些环节完整走一遍,让手里同时拿着ESP32和TFT屏幕的你,不再对着资料发愁。

我写这篇内容的时候,按“从简单到复杂”的顺序来组织。只要你之前点亮过LED,或者跑通过一个Blink例程,就能跟上节奏;如果你已经能玩转SPI设备,也能在并口屏的性能优化、DMA配置这些章节里找到可用的细节。好,直接开始。

1. 看清需求:LCD屏驱动到底在解决什么问题

1.1 从“点灯”到“点亮屏幕”:单色屏、TFT屏与分辨率

很多新手拿到一块LCD屏,第一反应是“屏幕是不是就该像手机一样,插上电就显示画面”。实际上LCD屏跟单片机之间并没有一个通用的“视频线”。你看到的是MCU通过一组通信协议,把像素数据一列一列、一行一行地写到屏幕控制芯片内部的显存里,再由控制芯片驱动液晶分子翻转,最终显示出画面。

按照显示屏的类型,常见的有两种。一种是段码屏或者字符屏,比如电子表上那种数字显示,驱动方式比较原始,一般用HT1621这类芯片去扫描;另一种就是大家常说的TFT彩色屏,像1.8寸ST7735、2.4寸ILI9341,这类屏内部有完整的像素矩阵,每一个像素点由RGB三色子像素组成。这篇文章主要说的是后者。

分辨率决定了你有多少个像素点要处理。128x160的1.8寸屏,总共20480个像素;320x240的2.4寸屏,总共76800个像素。如果你用RGB565格式,也就是一个像素占2字节,一帧数据量分别是40KB和150KB。这个数字看起来不起眼,但放到8位或者部分32位MCU上,传输方式和速度就成了关键问题。这也是为什么驱动屏之前,我们要先把接口方案想清楚。

1.2 SPI、8080并口、I2C:三种常见接口到底差在哪

屏和MCU之间的“道路”决定了你能以多快的速度把像素数据搬运到显存里。目前LCD接口大致有三类。

I2C接口在低分辨率屏上比较常见,比如0.96寸OLED,以及部分小尺寸TFT。I2C只需要两根信号线,SDA和SCL,接线最省,但速度通常在400kHz到1MHz之间。对于需要频繁刷新动态数据、切换页面、做动画的彩色TFT屏来说,I2C完全是瓶颈,流畅度会很差。换句话说,I2C适合“静态显示”或者“每隔几秒变一下”的场景。

SPI接口是大多数TFT屏的选择。它至少需要SCLK、MOSI、DC、CS、RST这五根线。SPI可以跑20MHz到80MHz,一帧320x240的RGB565数据在40MHz下大概需要30ms左右,实际刷新率能到20到30fps,对绝大部分界面交互是足够的。

8080并口则是老牌LCD接口,从单片机驱动彩屏时代就存在。它用DB0到DB15这样的多根数据线并行传输数据,配合WR、RD、CS、DC、RST这些控制线。优势是每个时钟周期可以传8位或者16位数据,所以传输速率远高于SPI,特别适合像ESP32这类引脚资源充足的主控,在需要流畅动画或者高分辨率画面时首选。缺点是占用引脚多,接线复杂,而且代码里的引脚映射一旦错一位,画面就乱得没法看。

1.3 选型前必看的3个关键参数

决定一块屏幕是否适合你的项目,我建议先看这三个参数。

第一个是控制器型号。同样的物理尺寸和分辨率,屏背后的驱动IC可能完全不同。1.8寸屏常见ST7735S,1.3寸或1.54寸常见ST7789,2.4寸到3.5寸常见ILI9341,4寸以上还有ILI9488、ST7796等。驱动库基本都是按IC型号来适配的,买屏之前一定要确认型号,否则代码容易不兼容。

第二个是接口类型。有些屏只支持SPI,有些屏通过电阻选择可以切换SPI和8080并口,还有一些只支持并口。接口类型直接影响你能用的引脚数量和传输效率。买屏时看商品详情页的“接口方式”,或者直接问卖家要规格书,规格书里通常会写清楚芯片型号、工作电压、接口定义和背光参数。

第三个是背光与供电电压。多数TFT屏的逻辑电压是3.3V,背光LED灯串通常需要单独限流控制。如果你用的是5V供电的Arduino板子,还要注意电平转换;如果你用ESP32,3.3V IO可以直接驱动大多数屏幕控制IC,但背光电流仍要单独处理。别小看第三点,很多人屏幕能亮但颜色发暗、或者模块发烫,都是供电和背光环节出了问题。

2. 硬件选型与接线实操:SPI屏和8080并口屏各需要哪些线

2.1 常见LCD型号盘点与选购建议

先聊选购。以我自己买过的几块屏为例:

  • 1.8寸ST7735S,128x160,SPI接口,价格便宜,适合做小体积仪表,但分辨率低、可视角度一般。
  • 1.54寸ST7789,240x240,SPI接口,方屏显示效果好,交互界面可以做得比较精致,是小项目里很平衡的尺寸。
  • 2.4寸ILI9341,320x240,SPI或8080接口,老牌经典,资料最全,新手出现问题容易搜到解决方案。
  • 3.5寸ILI9488,480x320,通常为8080接口,SPI模式对通信速率要求很高,一般建议用并口或者RGB接口。

选购时,尽量选“模块化”的屏,也就是厂家已经帮忙把电平转换、背光限流电阻、甚至触摸芯片都集成好的成品模块。这样你只需要把模块的引脚接到主控上即可。如果买的是裸屏,还得自己配转接板,比较麻烦。另外,像“1.8寸TFT LCD分辨率128x160”这种词,搜索时很有用,你可以直接拿它去找对应的型号和库示例。

2.2 ESP32/ESP32-S2引脚分配与接线表

重点来了。ESP32和ESP32-S2的引脚资源不同,接线前最好先看一眼你手里的开发板原理图,确认引脚是否被板载Flash、LED、USB等占用了。下面是基于Arduino生态的一套稳妥接法,大家可以直接照着接,也可以按自己的板子调整。

SPI接线,以2.4寸ILI9341为例:

LCD引脚ESP32开发板ESP32-S2开发板
VCC3.3V3.3V
GNDGNDGND
CSGPIO5GPIO5
RSTGPIO4GPIO4
DCGPIO2GPIO2
MOSI/SDAGPIO23GPIO35
SCLK/SCLGPIO18GPIO36
LED(背光)3.3V串电阻或GPIO控制3.3V串电阻或GPIO控制

这里有几个细节要注意。ESP32-S2的VSPI/FSPI映射跟ESP32不完全一样,默认SPI引脚在不同库中可能不同,很多库允许自己在配置里定义,所以最终以代码为准。另外,ESP32-S2没有传统意义上的GPIO23/18作为SPI默认引脚,所以我建议了GPIO35/36,这些是ESP32-S2开发板上比较常用的可用引脚。

8080并口接线,以2.4寸ILI9341并口模块为例,16位数据线:

LCD引脚ESP32开发板说明
CSGPIO5片选
RSTGPIO4复位
DC(RS)GPIO2数据/命令选择
WRGPIO15写信号
RDGPIO16读信号,不读屏可接高电平或GPIO控制
DB0-DB7GPIO12, 13, 14, 25, 26, 27, 17, 16低8位数据线
DB8-DB15GPIO22, 21, 19, 18, 23, 33, 32, 35高8位数据线
LED3.3V串电阻或GPIO背光

并口接线容易出错的地方是:高8位和低8位一定要跟库里的定义一致。如果某一位接反,颜色会变得像花屏一样离谱,这时候优先检查每一根数据线是否按代码里的宏定义一一对应。另外,如果你的屏是8位并口而不是16位,可以省略高8位数据线,但驱动库初始化时要改成8位模式。

2.3 供电与背光:最容易忽略的两个坑

第一坑是背光。LCD屏模块上的LED脚标着背光,如果直接用3.3V和GND去驱动大尺寸屏的背光,可能亮度不足或电流过大。很多模块上已经有背光限流电阻,直接接3.3V没问题;但有些模块没有,长时间满电流运行会发烫、减寿。稳妥做法是接一个IO口,通过NPN三极管或者MOS管控制背光,配合PWM调节亮度,这样还能实现自动息屏。最简单的PWM亮度控制代码:

pinMode(LED_PIN, OUTPUT); analogWrite(LED_PIN, 128); // 0-255,128为半亮度

如果模块直接接3.3V亮度太高、或想软件调光,就用一颗NPN三极管搭一个低边开关,集电极接背光LED负极,发射极接地,基极串1k电阻接PWM引脚。这种接法能让你用PWM实现平滑的亮度渐变,比单纯开关背光实用得多。

第二坑是总线电平。有些屏幕控制器同时支持3.3V和5V逻辑,但很多TFT裸屏的IO电平上限是3.3V。ESP32本身是3.3V IO,所以直连没问题。但如果你的板子带5V的电平,比如老款Arduino,最好加电平转换,否则长期使用可能损伤屏幕时序电路。别小看这个坑,很多人一开始用5V板子点亮了,结果用几天屏幕就出问题。

3. 驱动代码实现:从初始化到显示一张图片

3.1 驱动框架选型:TFT_eSPI、Arduino_GFX还是LovyanGFX

硬件接好,接下来就是软件。Arduino生态里,LCD驱动库里最有名的三家是TFT_eSPI、Arduino_GFX和LovyanGFX。

TFT_eSPI是老牌库,由Bodmer维护,对ST7735、ST7789、ILI9341等大量IC支持很好。它的特点是通过修改User_Setup.h这个配置文件来定义引脚和屏幕型号,不用改代码,适合新手。缺点是配置时容易忘记改文件,或者搞错IC型号。

Arduino_GFX是moononournation维护的库,API跟Adafruit GFX接近,支持设备很多,也支持并口和RGB屏,配置方式比TFT_eSPI更灵活一些。

LovyanGFX主打性能和更多高级功能,比如DMA传送、双缓冲、多屏操作,在ESP32上跑分很高。缺点是学习曲线稍陡,API风格跟传统GFX不太一样。

我的建议:如果是新手第一次点亮屏幕,优先用TFT_eSPI,因为它网上资料最多,教程也最完整。如果是做稍微复杂一点的界面、或者需要特别流畅的动画,可以试试LovyanGFX。如果你的项目以后要接LVGL,那LovyanGFX和TFT_eSPI都有对应的LVGL移植示例,不用担心兼容性。

3.2 TFT_eSPI配置与SPI接线验证

以ESP32 + 2.4寸ILI9341 SPI为例,先安装TFT_eSPI库,然后找到Arduino的libraries文件夹下的TFT_eSPI/User_Setup.h,确认这些宏的值:

#define ILI9341_DRIVER #define TFT_CS 5 #define TFT_DC 2 #define TFT_RST 4 #define TFT_MISO 19 // 通常不用读屏的话也可不接 #define TFT_MOSI 23 #define TFT_SCLK 18

如果你的屏只写不读,绝大多数应用都不需要读,MISO可以不接,但很多屏模块上仍有MISO引脚,悬空即可。如果模块上MOSI和SDA两个标号都有,通常SDA就是MOSI。

配置好之后,可以先用官方示例中的graphicstest来验证。刷进去如果看到连续的色块、线条滚动,说明接线和初始化没问题;如果白屏、花屏,就进入后面的排错章节。

有一个小提示:TFT_eSPI的User_Setup.h里还有多个驱动宏,比如ST7789_DRIVER、ST7735_DRIVER,如果屏是ST7789但又没改驱动宏,会显示不出正确颜色或者花屏;反之,把ILI9341_DRIVER改成ST7789_DRIVER,同时确认显示屏分辨率设置,比如ST7789有240x240和240x320两种变体。这类“同尺寸不同IC”的情况是最容易踩的坑,买屏时多问卖家一句“主控是什么”能帮你省下大量排查时间。

3.3 8080并口模式下的代码差异

如果你的屏是8080并口模块,那么TFT_eSPI也支持,但配置方式和SPI不同。比如在User_Setup.h里要这样:

#define ILI9341_DRIVER #define TFT_CS 5 #define TFT_DC 2 #define TFT_RST 4 #define TFT_WR 15 #define TFT_RD 16 #define TFT_D0 12 #define TFT_D1 13 #define TFT_D2 14 #define TFT_D3 25 #define TFT_D4 26 #define TFT_D5 27 #define TFT_D6 17 #define TFT_D7 16 #define TFT_D8 22 #define TFT_D9 21 #define TFT_D10 19 #define TFT_D11 18 #define TFT_D12 23 #define TFT_D13 33 #define TFT_D14 32 #define TFT_D15 35

然后TFT_eSPI会自动启用8位或16位并行模式,前提是这些宏都定义在User_Setup.h里。需要注意的是,并口模式不经过SPI外设,而是用GPIO直接模拟总线时序,所以代码中对引脚的定义非常关键。部分板子如果同时使用并口和WiFi,要注意高位引脚是否和PSRAM、Flash等冲突,ESP32的GPIO16/17等通常没问题,但不同开发板差异很大。

还有一点,8080并口模式下,有些库会默认启用“读回”功能,也就是通过RD引脚读取屏幕显存内容。如果你的接线没接RD,或者没有接读取方向的那根线,有可能导致初始化卡住。解决办法是把RD引脚接高电平,或者在配置里关闭相关读回。

3.4 显示中文、图片与动态数据的完整流程

先说说显示中文。TFT_eSPI默认不支持中文文字,需要通过字库文件把字模转换成像素数据。最简单的方案是用LVGL的字体工具或者“img2lcd”之类的工具生成字模,再用drawBitmap把字模画到屏幕上。如果你不想折腾字模,也可以用Adafruit GFX的字体机制,但中文字库文件很大,不适合直接放在小Flash的板子上。

这里给一个比较实用的方案:用TFT_eSPI的pushImage函数显示图片,配合在线图片转换工具把JPG/PNG转成RGB565数组。比如一张64x64的图标,转换后会生成一个uint16_t数组,显示时:

tft.pushImage(x, y, 64, 64, image_data);

动态数据部分,比如显示温湿度或者时间,要在循环里反复调用drawString或者setCursor。注意刷屏区域的频率控制:

tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setCursor(10, 20); tft.print(temperature);

如果数值变化太快或者太慢,建议用“局部刷新”:只重画数值区域,而不是全屏clear。比如可以在数值显示区域先画一个底色矩形,再用设置背景色的方式覆盖旧值。这样做的好处是减少屏幕刷新次数,也能顺手降低对主循环的阻塞。

4. 实际操作中的常见问题与排错

4.1 花屏、白屏、颜色不对的一线排查顺序

我见过太多人花屏就怀疑屏坏了,其实大部分时候问题出在复位时序或驱动宏配置上。遇到白屏/花屏,按这个顺序排查。

第一步,确认背光亮不亮。不亮就看背光接线和供电,亮再继续。

第二步,看复位引脚。很多屏在初始化时需要复位,TFT_eSPI库会自动控制RST引脚;如果你RST接错引脚,初始化时序不对,屏幕就可能白屏。

第三步,看DC引脚。如果是SPI屏,DC引脚接错会导致数据被当成命令,或者命令被当成数据,结果是“有显示但完全错乱”,是很典型的花屏。

第四步,确认驱动宏和分辨率。ILI9341用了ST7735的驱动宏,或者分辨率设置错误,都会出现颜色偏移、显示区域不对的问题。在这一步,用官方的graphicstest测试例程是最好的验证手段。

第五步,确认时钟频率。有些屏或杜邦线质量不好,SPI跑到40MHz以上就会出现噪声干扰,导致颜色随机跳动。降低频率到10MHz或者20MHz试试,往往能直接解决。

4.2 SPI通信不稳定:时钟频率、杜邦线与片选

SPI不稳定主要三个原因。

第一个是频率过高。TFT_eSPI里可以设置SPI_FREQUENCY参数,默认可能是27MHz或40MHz,如果你用的杜邦线较长、又没有接地线,信号质量会变差。解决办法是把频率降到10MHz或20MHz,除非你确定线材足够短。

第二个是接线接触不良。很多模块的排针焊盘和杜邦线之间容易虚接,尤其是没有焊接排针、直接插在面包板上的时候。我建议屏幕模块用排线焊死,或者用质量好一点的母对母杜邦线,尽量让线短一些。这里多说一句,“SPI通信不生效”这个现象,很多时候就是接触不良造成的,拔插一次就好,但过一会儿又复发,这时候别怀疑代码,先换线材。

第三个是片选问题。如果是软件片选,库会在每次通信时手动拉低CS;如果另一个外设也在占用同一个SPI总线,或者CS接在了别的引脚上,就可能出现数据串扰。SPI总线的硬件片选和软件片选在库中都有定义,TFT_eSPI默认用软件片选,但片选引脚不能随便复用。

还有一个冷门问题:如果屏幕和SD卡共用SPI总线,SD卡的数据线干扰可能导致屏幕偶尔花屏。这时候可以给SD卡那条线留出单独的处理,或者降低SPI频率。如果你想用“spi硬件片选与软件片选”做一次完整的取舍分析,结论一般是:硬件片选能省代码,但引脚固定;软件片选灵活,但要在高频下注意GPIO翻转速度。

4.3 性能优化:DMA、双缓冲与帧率

当你发现屏幕显示一整个320x240的图片要几百毫秒时,自然会想优化。优化的关键有两个方向。

第一个是使用DMA。TFT_eSPI在ESP32上可以开启DMA来搬运数据,而不用CPU逐字节去写。用spi.beginTransaction等接口,或者调用库的pushImageDMA方法,都能减少CPU占用。代码如下:

tft.startWrite(); tft.pushImageDMA(0, 0, 240, 320, buffer); tft.endWrite();

第二个是双缓冲。也就是在内存中准备一个和屏幕大小相同的缓冲区,先在缓冲区里画好内容,再一次推到屏幕上。这样能避免用户看到“边画边闪”的情况。缺点是RGB565的320x240缓冲区需要150KB内存,ESP32-S2没有大PSRAM时会不够。可以考虑缩小缓冲区,只做局部双缓冲,或者用LovyanGFX的分区渲染。

如果这些优化还不够,就要考虑换8080并口屏或者使用ESP32-S3加PSRAM的方案,因为并口的并行数据吞吐量比SPI高很多。在做动画、游戏、或者高刷新率仪表盘时,这个差距会非常明显。

5. 进阶扩展:触摸、多屏与小项目实践

5.1 触摸屏接线与手势处理

带触摸的屏一般分为电阻触摸和电容触摸。常用的是XPT2046电阻触摸芯片,接线方式类似SPI,需要CLK、CS、DIN、DOUT和IRQ引脚。在TFT_eSPI里可以用TFT_eSPI::getTouch方法读取坐标:

uint16_t x, y; bool pressed = tft.getTouch(&x, &y);

电阻屏需要校准,一般读取触摸坐标后和屏幕分辨率做线性映射。电容触摸则通常通过I2C接口连接一个触摸控制器,比如FT6236、CST816S,使用对应的触摸库读取坐标。手势处理上,可以检测按下和抬起之间的坐标差,判断是点击、滑动还是长按。实际做界面时,我建议把“触摸按下”和“触摸释放”分开处理,避免按键误触发。

5.2 多屏、分屏与低功耗显示

ESP32作为主控,可以同时接多块屏幕。如果是两块SPI屏,最简单的方式是把CS分成两个引脚,共用SCLK和MOSI;如果两块屏是同一个控制器型号,驱动起来比较简单,只要切换CS就可以分别操作。如果混合使用SPI和并口屏,要注意引脚的占用和速度匹配,一般不太建议但也不是不行。

分屏显示的思路是:把屏幕划分为多个区域,每个区域维护独立的刷新脏标记,只有变化的部分才重绘。这样能极大降低刷屏负担,也降低了功耗。低功耗方面,可以做“息屏”:关闭背光,同时进入ESP32的modem sleep模式,按需求定时唤醒刷新。对于一些需要电池供电的小项目,这个处理能让续航提升不少。

5.3 实战:做一个带显示的小项目

这里分享一个我自己做过的小东西:一个桌面迷你气象站。用ESP32连WiFi获取天气接口数据,显示在1.54寸ST7789屏上,每30分钟刷新一次。

硬件清单:ESP32开发板、1.54寸ST7789屏、一个DHT11温湿度传感器,可选,USB线供电。接线按照前面2.2的SPI方案。代码逻辑大致是:初始化屏幕,连接WiFi,请求天气API解析JSON,然后把天气图标、温度和湿度以局部刷新的方式更新到屏幕上。代码量不大,但把SPI驱动、HTTP请求、JSON解析、局部刷新都串起来了。

如果你想做更流畅的界面,可以考虑加LVGL。LVGL和TFT_eSPI配合,可以做按钮、进度条、列表这些组件,配合触摸屏就能做一个完整的嵌入式UI。LVGL的移植核心是提供显示缓冲区刷新函数,Arduino_GFX和LVGL官方都有对应示例,照着改一下User_Setup和lv_conf.h里的颜色深度、缓冲区大小即可。

最后再说两句

在实际操作中我最深的体会是:LCD驱动本身并不难,难的是你第一次面对一个花花绿绿、时序复杂的模块时,很容易被各种“可能原因”淹没。所以我的建议一直很简单:先把接线确认三遍,再确定驱动IC型号,最后用官方示例点亮,不要一开始就想着自己写底层时序。很多人卡住,都是因为忽略了一个引脚定义或者驱动宏。

还有一个你们一定会碰到的小技巧:如果显示区域只用了屏幕的一半,剩下的半屏是黑边或者乱码,优先检查分辨率宏和初始化时传入的偏移参数。比如ST7789常见的是240x240屏,但它内部还有240x320的版本,库里的偏移量和尺寸要跟实际模块一致。这个调整参数的过程其实比想象中频繁,尤其当你买过不同批次、不同封装的小屏之后,你会回来感谢这句话。

希望这篇指南能帮你把屏幕点亮。等你的第一块屏幕跑起来,你就知道ESP32这波操作,其实比想象中简单不少。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 1:41:12

3ds Max角色绑定全解析:Bones刚性连接与Biped软性蒙皮实战

简介:这份PPT课件面向三维动画初学者与角色动画方向的学生,系统讲解3ds Max中角色动画设计的骨骼绑定技术,帮助读者理解从建模到骨骼连接、动作调节的完整解决方案。内容围绕内置Bones骨骼系统与Character Studio工具展开,涵盖刚性…

作者头像 李华
网站建设 2026/9/23 1:40:22

用C++ Qt还原保卫萝卜:课设塔防游戏架构与实现全解析

简介:这是一份基于C实现的保卫萝卜塔防游戏课程设计项目,以经典塔防玩法为原型,覆盖从游戏界面、防御塔建造升级到怪物波次、金币生命等核心机制,适合正在学习C游戏编程、需要完成大作业或课程设计的本科学生参考。压缩包共294个文…

作者头像 李华
网站建设 2026/9/23 1:39:28

PaddleHub 安装指南:环境依赖、pip 安装与网络/离线使用说明

PaddleHub 安装指南:环境依赖、pip 安装与网络/离线使用说明 【免费下载链接】PaddleFormers PaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFor…

作者头像 李华
网站建设 2026/9/23 1:38:40

MATLAB实现JPDA多目标跟踪:概率关联与航迹更新

简介:本资源是一份面向初学者的JPDA多目标跟踪算法实践材料,聚焦航迹关联核心问题,适用于雷达、视频监控等传感器数据处理场景下的算法学习与Matlab仿真入门。压缩包共2个文件,均为MATLAB源码(.m格式)&…

作者头像 李华