2. 单片机驱动LCD的基本流程:初始化时序、写寄存器、写GRAM、刷新显示
驱动一块LCD TFT屏,本质上是单片机按照屏厂规定的时序协议,通过并行或串行接口向屏的控制IC发送指令和数据。整个流程可以归纳为四个核心步骤:初始化时序 → 写寄存器配置 → 写GRAM(显存) → 刷新显示。任何一步出现时序偏差、电平错误或指令遗漏,都会导致黑屏、花屏或显示异常。
2.1 驱动流程总览
下图展示了从单片机上电到屏幕正常显示的标准数据流与指令流关系:
2.2 初始化时序
初始化时序是驱动的基础,必须在写任何寄存器之前严格满足。典型初始化时序包含以下阶段:
| 阶段 | 操作 | 典型时间要求 | 故障后果 |
|---|---|---|---|
| 1. 电源稳定 | VCC / IOVCC 达到工作电压 | ≥ 10 ms | 复位失败,IC 不响应 |
| 2. 硬件复位 | RESX 引脚拉低 → 拉高 | 低电平 ≥ 10 μs,释放后等待 ≥ 120 ms | 寄存器状态不确定,花屏 |
| 3. 软件复位 | 发送 0x01 命令(SWRESET) | 等待 ≥ 5 ms | 部分寄存器未复位,显示异常 |
| 4. 退出睡眠 | 发送 0x11 命令(SLPOUT) | 等待 ≥ 120 ms | 屏幕不亮或显示不全 |
常见故障:硬件复位时间不足(RESX 低电平过短)或退出睡眠后等待时间不够,是导致“上电后屏幕无反应”的最常见原因。建议在代码中增加
delay_ms(150) 确保稳定。
2.3 写寄存器配置
初始化时序完成后,需要通过写寄存器来配置屏的工作模式。寄存器写入遵循固定的命令/数据协议:
- 命令周期:DCX(数据/命令选择)引脚置低,写入命令字节。
- 数据周期:DCX 置高,写入一个或多个数据字节。
- 参数长度:每个命令对应的参数个数由屏厂数据手册规定,不可多写或少写。
以下是一段典型的初始化寄存器配置代码(以 SPI 接口为例):
// 写命令函数
void LCD_WriteCmd(uint8_t cmd) {
DCX_LOW(); // 命令模式
CS_LOW(); // 片选使能
SPI_Transmit(cmd); // 发送命令字节
CS_HIGH(); // 片选释放
}
// 写数据函数
void LCD_WriteData(uint8_t data) {
DCX_HIGH(); // 数据模式
CS_LOW();
SPI_Transmit(data);
CS_HIGH();
}
// 初始化序列示例(ILI9341)
void LCD_Init(void) {
// 硬件复位 & 等待
RESX_LOW(); delay_ms(10);
RESX_HIGH(); delay_ms(150);
// 软件复位
LCD_WriteCmd(0x01); delay_ms(5);
// 退出睡眠
LCD_WriteCmd(0x11); delay_ms(120);
// 设置像素格式:16位色
LCD_WriteCmd(0x3A);
LCD_WriteData(0x55); // 16-bit RGB565
// 设置显示方向
LCD_WriteCmd(0x36);
LCD_WriteData(0x48); // MX, MV 位配置
// 打开显示
LCD_WriteCmd(0x29);
delay_ms(10);
}
排查要点:如果初始化后屏幕显示颜色错乱,优先检查
0x3A 像素格式寄存器是否与上位机发送的像素数据格式一致。RGB565 与 RGB888 混用会导致每个像素错位。
2.4 写GRAM(显存)
写GRAM是将像素数据写入屏内部显存的过程。关键步骤包括:
- 设置窗口地址:通过命令
0x2A(列地址)和0x2B(行地址)定义要写入的矩形区域。 - 启动写显存:发送命令
0x2C(RAMWR),随后连续发送像素数据。 - 数据顺序:通常从左到右、从上到下逐像素填充,具体由扫描方向寄存器
0x36控制。
写GRAM的时序要求:
| 参数 | 说明 | 典型值 |
|---|---|---|
| 窗口列起始 | X 起始坐标(2字节) | 0 ~ 239 |
| 窗口列结束 | X 结束坐标(2字节) | 0 ~ 239 |
| 窗口行起始 | Y 起始坐标(2字节) | 0 ~ 319 |
| 窗口行结束 | Y 结束坐标(2字节) | 0 ~ 319 |
| 像素数据格式 | RGB565:每像素2字节 | R[4:0] G[5:3] | G[2:0] B[4:0] |
// 设置窗口并填充颜色(全屏红色)
void LCD_FillScreen(uint16_t color) {
// 设置列地址:0 ~ 239
LCD_WriteCmd(0x2A);
LCD_WriteData(0x00); LCD_WriteData(0x00); // XS
LCD_WriteData(0x00); LCD_WriteData(0xEF); // XE (239)
// 设置行地址:0 ~ 319
LCD_WriteCmd(0x2B);
LCD_WriteData(0x00); LCD_WriteData(0x00); // YS
LCD_WriteData(0x01); LCD_WriteData(0x3F); // YE (319)
// 开始写显存
LCD_WriteCmd(0x2C);
for (uint32_t i = 0; i < 240 * 320; i++) {
LCD_WriteData(color >> 8); // 高字节
LCD_WriteData(color & 0xFF); // 低字节
}
}
性能提示:写GRAM是驱动中最耗时的操作。对于 240×320 分辨率、RGB565 格式,全屏刷新需要发送 240×320×2 = 153,600 字节。建议使用 DMA 或 SPI 硬件 FIFO 加速,避免 CPU 轮询阻塞。
2.5 刷新显示
刷新显示是驱动流程的最后一步,但不同屏的刷新机制存在差异:
- 自动刷新:大多数 TFT 屏(如 ILI9341、ST7789)在写完 GRAM 后自动将显存内容映射到面板,无需额外命令。
- 手动刷新:部分屏(如 SSD1963)需要发送
0x2C或特定刷新命令来触发显示更新。 - 局部刷新:通过设置小窗口并只写入变化区域,可以大幅提升帧率,降低功耗。
刷新显示相关的常见故障:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 屏幕全白/全黑 | 未发送 0x29(DISPON)或睡眠未退出 | 检查初始化序列最后是否打开显示 |
| 图像撕裂(tearing) | 写入速度与面板刷新不同步 | 启用 TE(Tearing Effect)引脚或使用帧同步 |
| 图像错位/偏移 | 窗口地址设置错误或扫描方向不对 | 核对 0x2A/0x2B 坐标范围与 0x36 方向位 |
| 颜色反转 | 像素格式或字节序错误 | 检查 0x3A 设置与数据发送的字节顺序 |
2.6 流程总结与故障排查清单
将上述四个步骤串联起来,形成完整的驱动流程。当屏幕显示异常时,按以下清单逐级排查:
- 上电与复位:用示波器测量 RESX 引脚,确认低电平宽度 ≥ 10 μs,释放后等待 ≥ 120 ms。
- 初始化时序:检查退出睡眠(0x11)后的延时是否足够,部分屏需要 150 ms 以上。
- 寄存器配置:逐条核对初始化命令与数据手册,重点检查像素格式(0x3A)和显示方向(0x36)。
- 写GRAM:确认窗口地址范围正确,像素数据字节顺序与格式匹配。
- 刷新显示:确认已发送 0x29 打开显示,且没有误发睡眠命令(0x10)。
推荐工具:使用逻辑分析仪抓取 SPI/8080 接口的波形,对比数据手册时序图,可以快速定位初始化时序中的延时不足或命令遗漏问题。