4. 初始化序列编写:从数据手册提取初始化命令、SPI/8080时序实现、初始化代码实战

说实话,LCD驱动这块,很多人一上来就怼着刷屏代码调,结果画面花屏、闪烁、颜色不对,折腾半天发现是初始化没写好。我早期做项目时就吃过这个亏——一块ST7789的屏,怎么调都偏色,最后拿示波器一抓,发现初始化序列里少发了一条命令。

初始化序列,说白了就是告诉LCD芯片:「我要开始用你了,请按我的规矩来」。这一步做扎实了,后面刷屏才稳。今天咱们就手把手把这事捋清楚。

4.1 数据手册里的初始化命令怎么找?

拿到一块新屏,第一件事不是写代码,是翻数据手册。我习惯先看这几个地方:

  • Command Table:命令列表,一般在手册后半部分
  • Initial Sequence:有些厂商会直接给一段推荐的初始化流程
  • Power On Sequence:上电时序,这个漏了屏直接不亮

以常见的ILI9341为例,它的初始化命令大概长这样:

命令 参数 说明
0x01 无 软件复位
0x11 无 退出睡眠模式
0x36 1字节 存储访问控制(决定扫描方向)
0x3A 1字节 像素格式(16位/18位)
0x29 无 打开显示
我的小技巧: 把数据手册里的命令表截图存下来,写代码时对照着看,比来回翻PDF快得多。我一般还会在命令旁边手写备注,比如「这条不加会花屏」之类的。

4.2 SPI与8080时序,到底选哪个?

这个问题我经常被问到。其实选择很简单:

  • SPI:引脚少(4线或3线),适合引脚紧张的MCU,但速度上限低
  • 8080并口:引脚多(至少8条数据线+控制线),但速度快,适合大屏高刷

我个人的经验是:320×240以下的小屏,SPI完全够用;再往上,尤其要跑动画或视频的,老老实实上8080。

来看SPI的时序实现。以写命令为例:

// SPI写命令(DC=0表示命令,DC=1表示数据)
void LCD_WriteCmd(uint8_t cmd) {
    DC_LOW();           // 命令模式
    CS_LOW();           // 片选使能
    SPI_TransferByte(cmd);
    CS_HIGH();          // 片选释放
}

8080并口稍微复杂一点,但核心逻辑一样:

// 8080写命令
void LCD_WriteCmd(uint8_t cmd) {
    DC_LOW();           // 命令
    RD_HIGH();          // 读禁止
    WR_LOW();           // 写使能
    DATA_PORT = cmd;    // 数据总线
    WR_HIGH();          // 锁存数据
}
注意: 8080时序里,WR的上升沿才是数据锁存时刻。我曾经因为WR拉高太快,数据还没稳定就锁存了,结果屏上全是乱码。后来在WR上升沿前加了100ns的延时才解决。

4.3 初始化代码实战:一步一步来

好,理论说完了,咱们直接上代码。下面是一份完整的ILI9341初始化序列,我把它拆成了几个步骤:

  1. 硬件复位:拉低RST引脚至少10ms
  2. 软件复位:发0x01命令
  3. 退出睡眠:发0x11,然后等120ms
  4. 配置参数:发0x36、0x3A等
  5. 打开显示:发0x29
void LCD_Init(void) {
    // 1. 硬件复位
    RST_LOW();
    delay_ms(10);
    RST_HIGH();
    delay_ms(120);  // 等内部晶振稳定

    // 2. 软件复位
    LCD_WriteCmd(0x01);
    delay_ms(120);

    // 3. 退出睡眠模式
    LCD_WriteCmd(0x11);
    delay_ms(120);

    // 4. 设置像素格式为16位
    LCD_WriteCmd(0x3A);
    LCD_WriteData(0x55);  // 0x55 = 16位色

    // 5. 设置扫描方向(根据你的屏安装方向调整)
    LCD_WriteCmd(0x36);
    LCD_WriteData(0x48);  // 竖屏模式

    // 6. 打开显示
    LCD_WriteCmd(0x29);

    // 7. 清屏
    LCD_Fill(0x0000);  // 黑色
}
关键点: 每条命令之间的延时不是随便写的。数据手册里会写「Exit Sleep」后需要等120ms,这个时间不能省。我见过有人为了省这120ms把延时改成10ms,结果屏一直闪。

4.4 初始化流程的SVG结构图

下面这张图把整个初始化流程串起来了,方便你对照着写代码:

LCD初始化流程结构图 LCD初始化流程结构图 1. 上电 2. 硬件复位 3. 软件复位 4. 退出睡眠 5. 配置参数 6. 打开显示 注意事项 • 硬件复位至少10ms • 退出睡眠后等120ms • 参数顺序不能乱 • 最后才打开显示

4.5 避坑指南:我踩过的几个坑

写初始化代码这么多年,有些坑我至今记忆犹新:

  • 坑一:复位后不等够时间——屏内部晶振还没稳定,发命令它不理你
  • 坑二:命令和数据搞混——DC引脚电平反了,屏把数据当命令解析,画面直接崩
  • 坑三:参数写错位——比如0x3A的参数应该是0x55,写成0x5A,颜色就全乱了
  • 坑四:初始化顺序不对——有些屏必须先配参数再开显示,顺序反了直接黑屏
我的调试习惯: 每次发完一条命令,用示波器抓一下DC和SCLK的波形,确认时序对不对。尤其是刚开始调新屏的时候,这一步能省下大半天排查时间。

嗯,初始化这块其实不难,但细节特别多。你只要把数据手册啃透,时序写对,代码一步步来,基本不会出大问题。下次咱们聊聊刷新率优化,那个才是真正考验功夫的地方。