一、LCD接口协议全景图
做嵌入式驱动开发这些年,我接触过的LCD接口少说也有七八种。每次带新人,他们总会问:「这么多接口,到底该选哪个?」
其实这个问题没有标准答案。不同的接口,对应不同的应用场景。我习惯先画一张图,把接口的层级关系理清楚。
这张图我每次培训都会拿出来。你想想看,从并行到串行,再到差分信号,本质上都是在解决同一个问题:如何在有限的引脚和功耗下,把图像数据又快又好地传过去。
二、RGB接口——最直接的并行接口
2.1 基本原理
RGB接口,说白了就是把每个像素的R、G、B数据,通过并行数据线直接送给LCD。没有缓存,没有协议栈,就是硬传。
我记得第一次调RGB接口的屏,用的是STM32F4的FSMC。当时心想:这还不简单?结果一上电,屏幕全是雪花。后来才发现,是时序没配好。
RGB接口的信号线包括:
- 数据线:R[7:0]、G[7:0]、B[7:0](24位真彩色),也有16位或18位的
- 同步信号:VSYNC(帧同步)、HSYNC(行同步)、DE(数据使能)
- 时钟:PCLK(像素时钟)
关键点:RGB接口没有显存!LCD控制器必须持续不断地送数据。一旦停止,屏幕就黑了。
2.2 时序参数
做RGB接口驱动,最头疼的就是时序。我列个表,大家对照着看:
| 参数 | 说明 | 典型值(800x480) |
|---|---|---|
| HBP | 行同步后肩 | 46 PCLK |
| HFP | 行同步前肩 | 16 PCLK |
| VBP | 帧同步后肩 | 23 行 |
| VFP | 帧同步前肩 | 10 行 |
| PCLK | 像素时钟频率 | 33.3 MHz |
⚠️ 我曾经踩过的坑:HBP和HFP配反了,屏幕显示整体偏移。查了两天才发现,是数据手册里「同步脉冲极性」没注意。有的屏是正极性,有的是负极性,千万要看清楚。
2.3 驱动代码片段
以STM32为例,配置RGB接口的时序:
/* RGB时序配置 - 以800x480为例 */
LCD_Timing_TypeDef timing;
timing.HorizontalSync = 1; // 行同步脉冲宽度
timing.HorizontalBackPorch = 46; // 行后肩
timing.HorizontalFrontPorch = 16;// 行前肩
timing.VerticalSync = 1; // 帧同步脉冲宽度
timing.VerticalBackPorch = 23; // 帧后肩
timing.VerticalFrontPorch = 10; // 帧前肩
/* 配置极性 */
timing.VSyncPolarity = 0; // 低电平有效
timing.HSyncPolarity = 0; // 低电平有效
timing.DEPolarity = 1; // 高电平使能
timing.PCLKPolarity = 0; // 下降沿采样
HAL_LTDC_Init(&hltdc, &timing, 800, 480);
三、MCU 8080接口——带缓存的并行接口
3.1 为什么叫8080?
这个名字源自Intel 8080处理器。说白了,就是CPU直接往LCD的GRAM里写数据。LCD内部自带显存,CPU写完就可以去干别的事。
我个人觉得,8080接口是新手最容易上手的。因为它和操作SRAM几乎一样。
3.2 信号与操作
8080接口的信号线:
- CS:片选
- RS:命令/数据选择(也叫DC)
- WR:写使能
- RD:读使能
- D[15:0]:数据总线(8位或16位)
写一个像素的流程:
- 拉低CS,选中LCD
- 拉低RS,发送写GRAM命令
- 拉高RS,发送像素数据
- 拉高CS,结束传输
💡 我的经验:8080接口的读写速度,取决于MCU的GPIO翻转速度。如果用FSMC硬件接口,可以轻松跑到10MHz以上。如果用GPIO模拟,能到1MHz就不错了。
3.3 8080 vs RGB
| 对比项 | 8080接口 | RGB接口 |
|---|---|---|
| 显存位置 | LCD内部 | MCU/外部 |
| 刷新方式 | MCU主动写 | 持续刷新 |
| 引脚数 | 20-30根 | 30-40根 |
| 适合分辨率 | ≤ 320x240 | ≥ 480x272 |
| MCU负载 | 低(写完就释放) | 高(持续DMA) |
四、SPI接口——最省引脚的串行接口
4.1 为什么用SPI?
SPI接口,说白了就是「穷人的LCD接口」。只需要4根线:SCLK、MOSI、MISO、CS。有些屏连MISO都省了,3根线就能搞定。
我做过一个项目,MCU只有20个引脚,还要接传感器、按键、无线模块。最后LCD只能走SPI,虽然刷新慢了点,但够用。
4.2 SPI LCD的两种模式
- 命令模式:发送初始化命令、设置坐标等
- 数据模式:连续发送像素数据
驱动代码示例:
/* SPI写命令 */
void LCD_WriteCmd(uint8_t cmd) {
LCD_CS_LOW();
LCD_DC_LOW(); // 命令模式
SPI_Transmit(&cmd, 1);
LCD_CS_HIGH();
}
/* SPI写数据 */
void LCD_WriteData(uint16_t data) {
uint8_t buf[2];
buf[0] = data >> 8;
buf[1] = data & 0xFF;
LCD_CS_LOW();
LCD_DC_HIGH(); // 数据模式
SPI_Transmit(buf, 2);
LCD_CS_HIGH();
}
⚠️ 注意:SPI接口的LCD,刷新率受限于SPI时钟。SPI时钟20MHz时,320x240的屏全屏刷新大约需要30ms。如果要做动画,建议用RGB或MIPI。
五、LVDS接口——差分信号传输
5.1 为什么需要LVDS?
RGB接口在高分辨率下,有两个致命问题:
- 引脚太多(24位RGB需要30多根线)
- 信号容易受干扰(高频信号在长线上衰减严重)
LVDS用差分对传输,一对线就能传7位数据。说白了,就是用「两根线拧在一起」的方式,把干扰抵消掉。
5.2 LVDS的通道结构
典型的LVDS接口有4对数据通道 + 1对时钟通道:
- 通道0:R0-R5 + G0
- 通道1:G1-G5 + B0-B1
- 通道2:B2-B5 + HSYNC + VSYNC + DE
- 通道3:R6-R7 + G6-G7 + B6-B7(可选,用于6位转8位)
我调过一款7寸1024x600的屏,用的就是LVDS。当时布线的时候,差分对必须等长,差一点屏幕就闪。嗯,这个坑我记忆犹新。
六、MIPI DSI接口——手机主流
6.1 MIPI DSI是什么?
MIPI DSI是移动行业处理器接口联盟定义的显示接口。现在几乎所有手机、平板的屏幕都在用。
它和LVDS类似,也是差分信号。但MIPI更灵活:
- 支持多种数据通道:1/2/3/4 Lane
- 支持双向通信:可以读寄存器、读状态
- 支持多种视频模式:命令模式、视频模式、突发模式
6.2 DSI的两种工作模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 命令模式 | 类似8080,LCD自带GRAM | 低功耗、静态画面 |
| 视频模式 | 类似RGB,持续刷新 | 高帧率、视频播放 |
6.3 DSI初始化流程
我调MIPI屏时,最怕的就是初始化序列。每个屏厂的初始化代码都不一样。这里给个通用流程:
/* MIPI DSI初始化步骤 */
1. 配置DSI主机时钟(通常从PLL分频)
2. 设置Lane数和速率(如4 Lane, 500Mbps)
3. 发送DCS命令初始化LCD
- 0x11: 退出睡眠模式
- 等待120ms
- 0x29: 开启显示
- 0x2C: 内存写命令
4. 配置视频模式时序(HBP, HFP, VBP, VFP等)
5. 启动DSI传输
💡 我的建议:MIPI DSI的调试,最好用逻辑分析仪抓一下初始化序列。我曾经遇到一个屏,初始化命令发对了,但时序间隔不对,屏幕就是点不亮。后来用分析仪一看,发现DCS命令之间的延迟太短了。
七、接口选型总结
说了这么多,最后给个选型建议:
- 小尺寸、低分辨率(≤320x240):SPI或8080,引脚少,驱动简单
- 中尺寸、中等分辨率(480x272 ~ 1024x600):RGB或LVDS,刷新快
- 大尺寸、高分辨率(≥1280x720):MIPI DSI或LVDS,信号质量好
- 车载、工业长距离传输:LVDS,抗干扰能力强
我个人最常用的组合是:MCU带RGB接口 + 外部SDRAM做显存。性价比高,调试也方便。当然,如果你做手机,那MIPI DSI是唯一选择。
好了,这一章的内容就到这里。接口协议这东西,光看文档是不够的。有机会的话,拿块屏实际调一调,比看十遍文档都管用。