跳到主要内容

显示基础与接口

无论驱动哪种类型的屏幕,像素、色深、帧缓冲、显示方向与坐标系这些基础概念都是通用的;而屏幕与主控之间的数据通路(即显示接口)则直接决定了刷新带宽和引脚开销。本章介绍这两部分内容,作为后续各屏幕章节的基础。以下按 ESP32 生态中的常见方案讲解。

1. 显示的公共概念

1.1 像素与分辨率

屏幕上的画面由一个个像素(Pixel)组成。分辨率描述屏幕横向和纵向各有多少个像素,例如 240×320 表示横向 240 个、纵向 320 个像素。驱动屏幕的本质,是为每个像素指定要显示的颜色。

1.2 色深

色深(Color Depth)指每个像素用多少位(bit)来描述颜色,直接决定了一个像素占用的数据量:

色深每像素数据量可表示颜色典型场景
1bpp(单色)1 bit黑 / 白单色 OLED、RLCD、黑白墨水屏
RGB56516 bit(2 字节)65536 色嵌入式彩屏的主流格式
RGB88824 bit(3 字节)约 1677 万色高色彩要求的场景

RGB565 用 5 位表示红色、6 位表示绿色、5 位表示蓝色,在色彩效果和数据量之间取得平衡,是 ESP32 上彩屏开发最常用的格式。

RGB565 的位数分配

嵌入式 LCD 常用 RGB565,是因为一个像素正好占 16 位(2 字节),比 24 位 RGB888 少占三分之一的显存和传输带宽。对 SPI、I80 等接口而言,少传 1 字节通常能直接降低刷新压力,因此很多中小尺寸 LCD 示例和图形库默认使用 RGB565。

绿色分量占 6 位,是因为人眼对绿色亮度变化更敏感,给 G 多分配 1 位可让亮度过渡更细。这样总位数仍保持 16 位,同时把更多层级留给对视觉亮度影响较大的绿色通道。


由“分辨率 × 色深”可以算出一帧完整画面的数据量:

屏幕示例分辨率色深一帧数据量
0.96 英寸单色 OLED128×641bpp1 KB
1.28 英寸圆形 LCD240×240RGB565112.5 KB
2.4 英寸 LCD240×320RGB565150 KB
4.3 英寸 RGB 屏800×480RGB565750 KB

帧数据量直接影响两个关键因素:刷新一帧需要传输多少数据(影响帧率),以及缓存一帧画面需要多少内存(影响内存方案)。

1.3 帧缓冲与显存(GRAM)

对于需要持续扫描刷新的屏幕,当前画面的全部像素数据需要保存在一块内存中,这块内存称为帧缓冲(Frame Buffer)。它可能位于两个位置:

  • 屏幕侧:多数 SPI / I80 接口的屏幕,其驱动 IC 内部集成了显存(GRAM)。主控把像素数据写入 GRAM 后,驱动 IC 自行负责持续刷新面板。主控无需保存整帧画面,内存压力小,画面不更新时主控无需执行任何操作。
  • 主控侧:RGB 接口的屏幕没有 GRAM,主控必须在自己的内存中维护完整帧缓冲,并按固定时序不间断地向屏幕输出数据。当片内 RAM 不足以容纳完整帧缓冲时,就需要借助片外 PSRAM。以 800×480 RGB565 为例,一帧就需要 750 KB,超出多数 ESP32 型号的片内 RAM,因此这类 RGB 大屏的应用大多需要配备 PSRAM;分辨率较低的 RGB 屏若帧缓冲能放入片内 RAM,则未必需要。
QSPI 与 MIPI-DSI 屏幕

这两类屏幕两种情况都有,取决于驱动 IC 型号和工作模式:部分 QSPI 驱动 IC 内置 GRAM,用法接近 SPI,另一些不带 GRAM,需要主控持续输出画面。ESP32-P4 的 MIPI-DSI 使用 Video Mode,帧缓冲位于主控侧。

这是选择接口时最核心的区别之一:SPI 屏对主控内存要求低,RGB 屏则取决于帧缓冲大小,大尺寸、高分辨率屏通常需要 PSRAM

1.4 刷新与画面撕裂

屏幕并不会在写入后立即显示对应内容,驱动 IC 会按固定的刷新率(如 60 Hz)周期性地把显存内容扫描到面板上。如果主控写入 GRAM 的过程恰好跨越了一次扫描,屏幕上就会同时出现新旧两帧的内容,称为画面撕裂(Tearing)。

部分带 GRAM 的屏幕引出了 TE (Tearing Effect) 引脚,在两次扫描之间的间隙输出一个同步脉冲。主控可以等待该信号后再开始写入,使写入过程与屏幕扫描保持同步。要完全消除撕裂,还需要写入方向与扫描方向一致、写入速度跟得上扫描速度。主要显示静态内容、只偶尔更新画面的应用,一般无需处理撕裂问题。

有关撕裂的更多讲解,请参考 ESP-IoT-Solution 编程指南 - LCD 屏幕撕裂详解

1.5 全屏刷新与窗口刷新

带 GRAM 的屏幕支持窗口寻址(Window Addressing):先通过命令指定一个矩形区域,之后写入的像素数据只落在该区域内。因此更新画面时不必重传整帧,只刷新变化的部分即可,这能显著降低传输量。LVGL 等图形库的“局部刷新”就是基于这一机制实现的。

信息

墨水屏的“局刷”是另一个概念,它涉及电泳粒子的驱动波形,详见 E-Paper 章节

1.6 显示方向与坐标系

屏幕的原生方向由面板和驱动 IC 的行列排列决定。以原生宽度为 W、高度为 H 的屏幕为例,通常将左上角定义为坐标原点 (0, 0),X 轴向右递增,Y 轴向下递增。模组安装到设备后,屏幕的物理方向可能与原生方向不同,因此需要将显示内容旋转到对应方向。

显示方向改变后,图形库使用的逻辑坐标系也会随之改变。以原生画面顺时针旋转为例,原坐标 (x, y) 与旋转后坐标的关系如下:

顺时针旋转角度逻辑宽度 × 高度原坐标映射到旋转后坐标
W × H(x, y)
90°H × W(H - 1 - y, x)
180°W × H(W - 1 - x, H - 1 - y)
270°H × W(y, W - 1 - x)

实际开发时通常不需要手动计算这些坐标,屏幕驱动或图形库会提供显示方向设置。按照像素转换发生的位置,旋转可分为两种方式:

旋转方式实现原理特点
控制器侧旋转(通常称为硬件旋转)带 GRAM 的驱动 IC 通过行列交换和轴向翻转改变像素寻址方向,部分驱动 IC 使用 MADCTL 等寄存器控制使用驱动 IC 自身的寻址能力,主控无需重排整帧像素,也不需要增加完整的旋转缓冲区;可用方向取决于驱动 IC
主控侧软件旋转CPU、软件画布或 GUI 框架先转换帧缓冲区,再将转换后的像素写入屏幕不依赖驱动 IC 提供完整的旋转能力,但会增加内存占用、数据复制量和计算开销

对于 0°、90°、180°、270° 旋转,如果驱动 IC 支持所需方向,应优先使用控制器侧旋转。它直接使用屏幕控制器的寻址功能,配置完成后仍可按旋转后的逻辑坐标绘图。驱动 IC 不支持行列交换,或者应用需要其他角度和图像变换时,再使用主控侧软件旋转。

Arduino_GFX 的 setRotation()、u8g2 构造器中的 U8G2_R0U8G2_R3 等接口用于设置显示方向。设置后,图形库会按照目标方向调整逻辑坐标和宽高;像素最终由驱动 IC 重新寻址,还是在主控侧完成转换,取决于具体驱动和缓冲方式。

旋转参数以库和驱动定义为准

不同图形库对旋转编号和起始方向的定义不完全相同,部分驱动 IC 也只支持轴向翻转,不能完成 90° / 270° 的行列交换。设置方向前,应查阅所用图形库和驱动的说明;设置后,应读取图形库提供的逻辑宽度和高度,并检查四角的图形是否完整。自行编写驱动时,还需确认不同方向下的窗口寻址偏移。

触摸 IC 通常仍按触摸面板的原生方向输出坐标。显示方向改变后,触摸坐标需要执行相同的轴交换和镜像变换,否则触点位置会与画面错位。具体处理方法见 触摸控制的“坐标与显示的对齐”章节

2. 显示接口对比

屏幕与主控之间常见的接口如下表,核心差异在于数据线数量(决定带宽)、实际占用的 IO 数(决定引脚开销)以及屏端是否带 GRAM(决定主控内存需求)。表中 IO 数为含时钟、片选、命令 / 同步等控制线的大致范围,复位、背光等可选引脚未计入:

接口数据线约占用 IO 数典型带宽屏端 GRAM典型应用
I2C1(双向)2(与其他 I2C 器件共用)≤ 1 Mbps0.96 英寸等小尺寸单色 OLED
SPI(4 线)14~540~80 Mbps3.5 英寸以下彩屏、墨水屏、RLCD
QSPI46~7理论峰值为 SPI 的 4 倍取决于驱动 IC1~2 英寸高分辨率 AMOLED
I80(8080 并口)8 / 1611~20较高中小尺寸 LCD
RGB 并口8 / 16 / 18 / 2412~283.5 英寸及以上大屏
MIPI-DSI1~2 条数据 Lane,另有 1 条时钟 Lane4~6(即 2~3 对差分线)很高无(Video Mode)高分辨率屏(ESP32-P4)

2.1 SPI:最常用的接口

SPI 是 ESP32 上最常见的屏幕接口,引脚少、接线简单,几乎所有系列的 ESP32 都支持。典型的 4 线 SPI 屏幕模块引脚如下(与微雪屏幕模块的丝印对应):

引脚说明
VCC / GND电源
DIN(MOSI)数据线,主控 → 屏幕
CLK(SCLK)时钟线
CS片选,低电平有效
DC命令 / 数据选择:低电平表示发送命令,高电平表示发送像素数据
SDO(MISO)可选的数据线,屏幕 → 主控,用于读取 ID、状态或显存。多数应用只写不读,可以不连接
RST复位,低电平有效。部分模块可以省略,驱动代码中复位引脚参数填 -1
BL背光控制(LCD 特有,可接 PWM 调节亮度)

其中 DC 引脚是显示 SPI 相较普通 SPI 多出的关键信号:屏幕驱动 IC 通过该引脚的电平,区分收到的字节是命令还是数据。RST 能否省略,以模块原理图和驱动要求为准。

2.2 帧率的三个环节

日常所说的“帧率”实际包含三个相互独立的环节,画面的实际流畅度由三者中的最小值决定:

  1. 渲染帧率:主控生成图像数据的速率。取决于主控性能与画面复杂度(局部更新通常快于全屏更新),是动态变化的。

  2. 接口帧率:主控连续传输完整画面时,显示接口能达到的速率。由接口带宽与一帧数据量决定:

    接口帧率上限 ≈ 接口带宽 ÷ 一帧数据量

    该式为理论上限,实际会低一些,估算时需要留出余量。

  3. 屏幕刷新率:驱动 IC 将显存内容扫描到面板的速率(见刷新与画面撕裂)。SPI / I80 屏由驱动 IC 自行决定(可通过命令配置),与主控的传输速率无关;RGB 屏没有这层解耦,主控输出的过程本身就是屏幕扫描的过程。

实际帧率为什么低于估算值

SPI、QSPI 和 I80 存在命令、事务间隔和 DMA 分块的开销;RGB 和 MIPI-DSI Video Mode 还需要计入有效画面之外的消隐时序。此外,内存和 DMA 带宽也可能成为瓶颈。

接口帧率是选型时最需要估算的环节。以 40 MHz 的 SPI 驱动 240×320 RGB565 屏幕为例:一帧约 1.23 Mbit,接口帧率上限约为 40 Mbps ÷ 1.23 Mbit ≈ 32 帧/秒(实际还有命令与协议开销,会更低一些)。这一估算可以解释几个常见现象:

  • SPI 驱动 240×240、240×320 这类中低分辨率屏幕时,通常能满足基础 GUI 的需求;分辨率继续提高后,全屏刷新的带宽很快成为瓶颈。
  • ESP32 生态中的小尺寸高分辨率 AMOLED 模组(如 410×502、466×466)多采用 QSPI,以缓解单线 SPI 的带宽压力。
  • 800×480 这类大屏一帧 750 KB,用单线 SPI 全屏传输难以达到流畅 GUI 所需的帧率,因此这类屏幕多采用 RGB、QSPI 或 MIPI-DSI 等带宽更高的接口。

若接口帧率估算充足而实际画面仍不流畅,瓶颈通常在渲染帧率,应优化绘制逻辑或降低画面复杂度,而非提高接口时钟。

2.3 各接口小结

  • I2C:引脚最少(与其他 I2C 器件共用总线),但带宽最低,只适合小尺寸单色 OLED。
  • SPI:只占 4~5 个 GPIO,全系列 ESP32 都支持,是最通用的选择;带宽有限,分辨率提高后需要换用其他接口。
  • QSPI:将 SPI 的 1 根数据线扩展为 4 根,像素数据阶段每个时钟最多传输 4 bit,理论峰值为 SPI 的 4 倍,是高分辨率 AMOLED 的主流接口。
  • I80:使用 8 位或 16 位并行数据总线,带宽高于单线 SPI,但加上 WR、DC、CS 等控制信号后通常需要 11~20 个 GPIO,在引脚紧张的 ESP32 上使用较少。
  • RGB:主控直接输出面板时序,带宽高、成本低,但占用 GPIO 多且必须在主控侧维护整帧缓冲(大屏通常依赖 PSRAM)。
  • MIPI-DSI:高分辨率、高刷新率屏幕常用的高速差分串行接口,引脚少带宽高,目前仅 ESP32-P4 支持。

3. ESP32 的显示接口支持

不同系列的 ESP32 支持的显示接口不同,选屏前需要确认主控能力:

接口支持的 ESP32 系列
I2C / SPI / QSPI全系列(通过通用 I2C / SPI 外设)
I80(原生)ESP32(I2S 的 LCD 模式)、ESP32-S2、ESP32-S3、ESP32-S31、ESP32-P4(专用 LCD 外设)
I80(模拟)ESP32-C5 / C6 / H2 等无原生 I80 外设的型号,可用 Parlio 外设模拟 I80 时序
RGBESP32-S3、ESP32-S31、ESP32-P4
MIPI-DSIESP32-P4

各系列的具体支持情况以 ESP-IoT-Solution:LCD 开发指南 - 支持的接口类型 为准。

按显示接口和应用规模,可参考以下方式选择:

  • ESP32-P4 接口最完整,是高分辨率屏幕的首选,但其本身不带无线连接,开发板通常另配 ESP32-C6 等模块提供 Wi-Fi 和 Bluetooth;
  • ESP32-S3 凭借专用 LCD 外设和可选的大容量 PSRAM,是目前带屏应用最常用的型号;
  • 新推出的 ESP32-S31 支持的接口类型与 ESP32-S3 相同,同规格 RGB 屏的实测帧率更高;
  • ESP32-C3 / C6 等主要使用通用 SPI,适合搭配中小尺寸 SPI 屏。

各型号在不同接口和分辨率下的实测帧率,可参考 乐鑫 LCD 应用开发笔记 中的 LVGL Benchmark 数据表。

在 Arduino 生态中,常见的 SPI、QSPI、I80 和 RGB 屏幕差异大多已由图形驱动库封装,常用的库有:

适用范围
GFX Library for Arduino (Arduino_GFX)彩屏通用图形库,支持 SPI / QSPI / I80 / RGB 多种总线与大量驱动 IC
LovyanGFX彩屏图形库,性能优秀,支持触摸与多种总线
TFT_eSPI经典 SPI 彩屏图形库,通过配置文件适配屏幕
u8g2单色屏图形库,OLED / RLCD 常用,字体资源丰富
GxEPD2墨水屏驱动库
微雪示例程序包各开发板 / 屏幕模块的官方驱动与示例,引脚和参数已适配好

各类屏幕分别适合用哪个库,在对应章节和 GUI 框架 章节中具体介绍。MIPI-DSI 等较新的接口目前主要依赖 ESP-IDF 及相关显示组件。

提示

使用微雪的带屏开发板(如 ESP32-S3-Touch-LCD 系列)时,屏幕已直连主控,无需接线;官方示例程序包中的引脚定义和初始化参数可直接使用。

4. 带 GRAM 屏幕的通用驱动流程

对于带驱动 IC 和 GRAM 的 SPI、I2C、I80 屏幕,驱动流程通常包括以下步骤,理解该流程有助于阅读后续章节的示例代码:

  1. 初始化总线:配置 SPI / I2C 等接口的引脚和时钟频率。
  2. 复位屏幕:拉低 RST 引脚一段时间后释放,使驱动 IC 回到确定状态。
  3. 发送初始化序列:向驱动 IC 写入一串配置命令,设置电源、扫描方向、像素格式等。这串命令由屏厂针对具体面板调校,一般直接使用微雪示例或驱动库中现成的初始化代码,无需自己编写。
  4. 设置写入窗口:指定接下来要更新的矩形区域(全屏或局部)。
  5. 写入像素数据:按选定的像素格式(如 RGB565)连续写入该区域的像素,画面随之显示。

后续更新画面就是重复第 4、5 步。使用 Arduino_GFX、u8g2 这类库时,第 1~3 步由库的 begin() 完成,第 4、5 步则被封装为 drawPixel()fillRect()drawBitmap() 等绘图 API。绘图 API 是立即向屏幕传输像素,还是先写入主控侧缓冲区、再由 flush()sendBuffer() 统一传输,取决于所用图形库及其缓冲模式。

其他类型的屏幕在此流程上有所不同:RGB 和 MIPI-DSI Video Mode 屏幕不采用“设置窗口再写入屏端 GRAM”的方式,应用在主控侧帧缓冲中绘制像素,LCD 外设按像素时钟和同步时序把帧缓冲内容持续输出到屏幕;墨水屏写入显示 RAM 后,还需要发送刷新命令并等待 BUSY 信号释放。

5. 延伸阅读


了解这些公共概念后,即可进入具体屏幕类型的章节。若尚未确定屏幕类型,可回到 显示屏总览 查看选型对比。