3. 初始化时序排查:检查复位时序、检查SPI/I8080初始化序列、检查睡眠唤醒命令

屏幕花屏,很多时候不是代码逻辑错了,而是初始化时序没给对。说白了,就是屏幕在上电到正常显示之间,有一连串的“握手”动作。任何一个动作没卡准点,屏幕就会给你点颜色看看——花屏、闪屏、甚至白屏。

我刚开始调屏幕驱动时,总觉得时序这东西差不多就行。结果有一次,一块新屏死活出不来画面,折腾了两天。最后发现,就是复位信号保持时间短了那么几毫秒。从那以后,我再也不敢小看初始化时序了。

3.1 复位时序——屏幕的“开机自检”

屏幕芯片内部也有个“小电脑”。上电后,它需要一段干净的时间来完成内部状态初始化。这个动作,就是靠复位引脚来触发的。

典型的复位时序要求是这样的:

参数 最小值 典型值 说明
上电后到复位拉低 10 ms 20 ms 等电源稳定后再复位
复位低电平保持 10 ms 20 ms 给芯片足够时间复位
复位拉高后等待 120 ms 150 ms 等待内部振荡器稳定
注意: 不同厂商、不同型号的屏幕,复位时序参数差异很大。有的屏幕要求复位低电平保持至少 5 ms,有的则要求 20 ms。一定要去翻数据手册的“Reset Timing”章节,别凭经验猜。

我见过一个案例,工程师把复位低电平时间写成了 1 ms。屏幕偶尔能亮,但大部分时间花屏。查了半天,就是这 1 ms 和 10 ms 的差距。你想想看,芯片内部状态还没清干净,你就开始发命令,不出问题才怪。

正确的复位流程应该是:

  1. 上电后,等待电源稳定(至少 20 ms)。
  2. 将复位引脚拉低,保持 20 ms。
  3. 将复位引脚拉高,等待 150 ms。
  4. 然后才能开始发送初始化命令。

代码实现上,我习惯这样写:

// 复位屏幕
void lcd_reset(void) {
    // 1. 等待电源稳定
    delay_ms(20);
    
    // 2. 拉低复位引脚
    LCD_RST_GPIO->BRR = LCD_RST_PIN;
    delay_ms(20);
    
    // 3. 拉高复位引脚
    LCD_RST_GPIO->BSRR = LCD_RST_PIN;
    delay_ms(150);
    
    // 4. 复位完成,可以开始初始化
}
小技巧: 如果你的 MCU 上电速度很快,而屏幕电源芯片启动慢,可以考虑在复位前加一个更长的延时。我个人习惯用 50 ms 起步,确保万无一失。

3.2 SPI/I8080 初始化序列——命令的“正确姿势”

复位完成后,就要开始给屏幕发初始化命令了。这些命令通常包括:软件复位、睡眠唤醒、像素格式设置、显示方向设置、伽马校正等。

但这里有个坑:命令的发送顺序和间隔,是有严格要求的。

我举个例子。很多屏幕在初始化时,需要先发一个 Software Reset (0x01) 命令,然后等待 5 ms,再发 Sleep Out (0x11) 命令,然后等待 120 ms,最后才能发 Display On (0x29) 命令。

如果你把 Sleep Out 和 Display On 连在一起发,中间没有延时,屏幕很可能就花屏了。为什么?因为屏幕从睡眠模式唤醒,内部需要时间稳定。

典型的 SPI 初始化序列代码:

// 发送初始化命令序列
void lcd_init_sequence(void) {
    // 软件复位
    lcd_write_cmd(0x01);
    delay_ms(5);
    
    // 睡眠唤醒
    lcd_write_cmd(0x11);
    delay_ms(120);
    
    // 像素格式:16位色
    lcd_write_cmd(0x3A);
    lcd_write_data(0x55);
    delay_ms(1);
    
    // 显示方向设置
    lcd_write_cmd(0x36);
    lcd_write_data(0x00);
    delay_ms(1);
    
    // 打开显示
    lcd_write_cmd(0x29);
    delay_ms(10);
}
核心要点: 每个命令之间的延时,不是随便写的。数据手册里通常会写明“Command Delay”或“Wait Time”。如果没写,就按经验值:普通命令 1-5 ms,睡眠唤醒 120 ms,软件复位 5 ms。

对于 I8080 接口,除了命令延时,还要注意读写时序。I8080 是并行接口,数据线多,时序要求更严格。我曾经遇到一个项目,用 I8080 接口驱动 3.5 寸屏,总是出现水平条纹。后来用逻辑分析仪抓波形,发现是写信号(WR)的保持时间不够。调整了 MCU 的 FSMC 时序参数后,问题就解决了。

3.3 睡眠唤醒命令——最容易忽略的“隐形杀手”

很多屏幕在上电后,默认是处于睡眠模式的。你必须先发 Sleep Out (0x11) 命令,把它唤醒,然后才能正常操作。

但这里有个细节:睡眠唤醒后,需要等待足够长的时间。

数据手册上通常会写:

  • Sleep Out 命令发出后,需要等待 120 ms(有些屏幕甚至需要 200 ms)。
  • 在等待期间,不能发送任何其他命令,否则屏幕可能进入未知状态。
  • 唤醒完成后,屏幕会自动进入正常模式。

我见过一个工程师,在 Sleep Out 后面只等了 10 ms,就开始发显示数据。结果屏幕花得像万花筒。他查了两天代码,最后发现是延时不够。加了 120 ms 延时后,一切正常。

避坑指南: 我曾经在 STM32F4 上驱动一块 ILI9341 屏幕,发现每次从睡眠唤醒后,屏幕颜色都偏色。后来仔细看数据手册,发现 Sleep Out 之后,还需要发一个 Display On 命令,并且中间要等 10 ms。很多人的初始化代码里只发了 Sleep Out,忘了 Display On,导致屏幕虽然亮了,但显示不正常。

完整的睡眠唤醒流程应该是:

  1. 发 Software Reset (0x01),等 5 ms。
  2. 发 Sleep Out (0x11),等 120 ms。
  3. 发其他初始化命令(像素格式、显示方向等)。
  4. 发 Display On (0x29),等 10 ms。
  5. 然后才能开始刷屏。

3.4 初始化时序排查流程图

下面这张图,是我自己总结的初始化时序排查流程。每次遇到花屏,我都会按这个顺序检查一遍,基本能定位 90% 的问题。

初始化时序排查流程图 开始排查 步骤1:检查复位时序 上电延时 → 复位低电平保持 → 复位后等待 时序正确? 否 调整复位延时参数 参考数据手册 是 步骤2:检查初始化序列 命令顺序 & 命令间延时 序列正确? 否 修正命令顺序/延时 参考初始化示例代码 步骤3:检查睡眠唤醒 Sleep Out → 等待 → Display On 唤醒正确? 否 增加唤醒等待时间 至少 120 ms 排查完成

这张图的核心逻辑很简单:按顺序排查,不要跳步。复位时序不对,后面的初始化序列再完美也没用。睡眠唤醒没做好,屏幕可能根本不会正常显示。

我的习惯: 每次拿到一块新屏幕,我会先写一个最简的初始化函数,只包含复位、睡眠唤醒、显示打开三个步骤。如果这个能正常显示,再逐步添加其他配置。这样能快速定位问题出在哪个环节。

嗯,初始化时序这块,说白了就是“慢工出细活”。别嫌延时浪费 CPU 时间,屏幕稳定显示比什么都重要。我曾经为了省那几十毫秒,把延时全删了,结果屏幕花得一塌糊涂。从那以后,我老老实实按数据手册来,再也不敢偷懒了。