2. LCD驱动原理:TFT-LCD显示、像素与帧缓冲区、RGB与SPI接口对比
做LCD驱动这么多年,我见过不少工程师一上来就翻数据手册找寄存器,结果调了三天屏幕还是花的。其实,搞懂LCD是怎么把数据变成图像的,比背寄存器重要得多。这一节,我们就从最核心的原理讲起。
2.1 TFT-LCD显示原理
TFT-LCD,全称是薄膜晶体管液晶显示器。说白了,它就是一个由无数个“小开关”控制的彩色像素阵列。
每个像素背后都有一个薄膜晶体管(TFT),它像个微型阀门。栅极(Gate)控制开关,源极(Source)给像素电容充电。电压不同,液晶分子的扭转角度就不同,透过背光的光量也就不同。
我习惯把TFT-LCD想象成一个巨大的“水龙头矩阵”:
- Gate线(行选):决定哪一行水龙头打开
- Source线(列数据):决定每个水龙头开多大
- 液晶分子:就是水龙头本身,控制水流(光)大小
你想想看,如果Gate线不按时打开,或者Source线上的电压没稳定,那这一行像素的颜色就全错了。我在调试一块320×240的屏时就遇到过,画面每隔几行就有一条亮线,最后发现是Gate扫描时序慢了半拍。
关键点:TFT-LCD是逐行扫描的。一行一行地给像素充电,然后保持住,直到下一帧刷新。这就是为什么帧率(Hz)决定了画面是否闪烁。
2.2 像素与帧缓冲区概念
一个像素由R、G、B三个子像素组成。常见的格式有RGB565(16位)、RGB888(24位)。
举个例子,一块320×240的屏,用RGB565格式:
- 每像素占2字节
- 一帧数据量 = 320 × 240 × 2 = 153,600 字节 ≈ 150KB
- 如果帧率60Hz,每秒需要传输 150KB × 60 ≈ 9MB 的数据
帧缓冲区(Frame Buffer),就是内存里专门划出来的一块区域,用来存放一帧完整的图像数据。MCU或CPU把要显示的内容写进这个缓冲区,然后LCD控制器或驱动芯片从缓冲区读数据,刷新到屏幕上。
我遇到过不少新手,直接在中断里往LCD写像素,结果画面撕裂。为什么?因为MCU在写缓冲区的同时,LCD控制器也在读缓冲区,数据打架了。解决办法就是双缓冲(Double Buffer):一个缓冲区给MCU写,另一个给LCD读,写完再交换。
我的经验:在资源紧张的MCU上,如果没法用双缓冲,至少保证在垂直消隐期(VBlank)更新缓冲区。这样能避免撕裂。
2.3 RGB接口与SPI接口对比
这是很多工程师选型时纠结的地方。我直接说结论:RGB接口快,但占引脚;SPI接口慢,但省引脚。
下面这张表是我自己总结的,你可以直接拿去用:
| 对比项 | RGB接口 | SPI接口 |
|---|---|---|
| 引脚数 | 16~24(数据线)+ 同步信号 | 4~6(CS、SCLK、MOSI、MISO、DC、RST) |
| 传输速度 | 高(并行,一次传多个像素) | 低(串行,一次传1位) |
| 是否需要帧缓冲区 | 通常需要(外部RAM或内部SRAM) | 部分需要(小屏可不用,大屏需要) |
| 典型应用 | 大屏(3.5寸以上)、高帧率 | 小屏(1.8寸以下)、低功耗、引脚受限 |
| 驱动复杂度 | 高(时序要求严格) | 低(SPI协议成熟) |
RGB接口,说白了就是直接把像素数据并行发给屏幕。它需要HSYNC(行同步)、VSYNC(帧同步)、DOTCLK(像素时钟)这些信号。MCU必须保证在DOTCLK的每个上升沿或下降沿,数据线上准备好一个像素的数据。一旦时序乱了,画面就会出现错位、花屏。
SPI接口就简单多了。它通过命令+数据的方式,把像素数据串行发给LCD驱动芯片(比如ILI9341、ST7789)。驱动芯片内部有自己的GRAM(显存),MCU只需要告诉它“我要在坐标(x,y)写颜色值”就行。
注意:SPI接口的LCD,写像素时通常要先发“列地址设置”和“页地址设置”命令,再发像素数据。如果地址设置错了,数据就会写到屏幕外面去。我曾经调试一块1.44寸的屏,画面一直偏移,最后发现是列地址起始值写错了。
下面这张图,是我画的SPI接口LCD驱动数据流,帮你理清MCU、帧缓冲区、LCD驱动芯片之间的关系:
从这张图你可以看到,MCU并不直接控制TFT面板。它只负责通过SPI总线,把像素数据写到LCD驱动芯片的内部GRAM里。驱动芯片自己会定时从GRAM读数据,刷新到TFT面板上。
这样做的好处是:MCU不用管像素时钟、行同步、帧同步这些麻烦事。坏处是:SPI速度有限,刷大屏或高帧率时,MCU会被占满。
选型建议:如果你的屏小于2寸,帧率要求不高(30Hz以内),SPI接口完全够用。如果屏大于3.5寸,或者需要60Hz以上刷新,老老实实用RGB接口吧。