第3章 并行接口时序基础:读/写时序图、建立时间、保持时间、访问周期

并行接口的时序,说白了就是CPU和LCD之间怎么“握手”通信。我刚开始做LCD驱动时,总觉得时序图看着像天书——一堆波形、箭头、标注,完全不知道从哪看起。后来被一块屏折腾了三天,才发现问题就出在建立时间差了那么几纳秒。嗯,从那以后我再也不敢小看时序图了。

3.1 读/写时序图——先看懂“握手”信号

并行接口的读写操作,本质上是CPU向LCD发送命令/数据(写),或者从LCD读取状态/数据(读)。每次操作都靠一组控制信号来协调:

  • CS (Chip Select):片选信号,低电平有效。只有CS拉低时,LCD才会响应总线上的操作。
  • RS (Register Select):寄存器选择。RS=0表示写命令/读状态,RS=1表示写数据/读数据。
  • RD (Read):读使能,低电平有效。拉低时LCD把数据放到数据总线上。
  • WR (Write):写使能,低电平有效。拉低时CPU把数据锁存到LCD内部。
  • D[7:0]:8位数据总线,双向传输。

我习惯把读写操作想象成一次“借书”的过程:CS是“图书馆开门”,RS是“你要借小说还是工具书”,RD/WR就是“把书递出来”或“把书放回去”。

3.1.1 写时序

写操作就是把数据从CPU送到LCD。典型的写时序流程如下:

  1. 先拉低CS,选中LCD芯片。
  2. 设置RS电平——写命令就拉低,写数据就拉高。
  3. 在数据总线上放好要发送的数据。
  4. 拉低WR,保持一段时间(WR低电平宽度),再拉高。
  5. LCD在WR上升沿锁存数据。
  6. 拉高CS,结束本次操作。

关键点:数据必须在WR上升沿之前稳定,并且在WR上升沿之后保持一段时间。这两个时间参数就是建立时间和保持时间。

3.1.2 读时序

读操作是从LCD读取数据到CPU。流程类似,但方向相反:

  1. 拉低CS,选中LCD。
  2. 设置RS电平——读状态拉低,读数据拉高。
  3. 拉低RD,LCD开始把数据放到总线上。
  4. CPU在RD上升沿读取总线上的数据。
  5. 拉高RD,LCD释放数据总线。
  6. 拉高CS,结束操作。

注意:读操作时,LCD需要一定时间才能把数据驱动到总线上(数据输出延迟)。如果CPU读得太快,可能读到的是上一笔数据或者高阻态。我曾经就因为RD脉冲太短,读回来的状态寄存器全是0xFF,排查了整整一个下午。

3.2 建立时间与保持时间——时序的“黄金法则”

这两个概念是所有同步接口的基石。你想想看,如果数据在时钟边沿到来时还在“抖动”,那锁存的结果就是不确定的。建立时间和保持时间就是为了保证数据在锁存时刻是稳定的。

参数 定义 典型值(以某款12864 LCD为例)
建立时间 (tsu) 数据在WR/RD有效沿之前必须稳定的最短时间 20 ns
保持时间 (th) 数据在WR/RD有效沿之后必须保持稳定的最长时间 10 ns
WR低电平宽度 (tWL) WR信号保持低电平的最短时间 40 ns
RD低电平宽度 (tRL) RD信号保持低电平的最短时间 40 ns
访问周期 (tcyc) 连续两次操作之间的最短间隔 100 ns

我个人的经验是:建立时间比保持时间更容易出问题。因为保持时间通常较短(10ns左右),而建立时间受总线电容、走线长度影响更大。如果你发现LCD偶尔显示异常,先检查建立时间是否留够了余量。

实战技巧:在写代码时,我习惯在WR拉低之前插入一个NOP(空操作)指令,或者在WR拉高之后再读数据。这样虽然牺牲了一点速度,但能保证时序余量充足。对于低速MCU(如12MHz的51单片机),一个NOP大约83ns,足够覆盖大多数LCD的建立时间要求。

3.3 访问周期——别让LCD“喘不过气”

访问周期是指连续两次操作之间必须等待的最短时间。为什么要有这个限制?因为LCD内部需要时间来处理刚收到的数据——比如更新显示缓存、切换内部状态机等。

如果你连续快速发送命令,LCD可能来不及处理,导致数据丢失或显示错乱。我记得有一次调试一个动画效果,画面总是闪烁,后来发现是连续写数据太快,访问周期没满足,LCD内部缓冲区溢出了。

访问周期通常包括:

  • 写周期:从WR下降沿到下一次WR下降沿的最短时间。
  • 读周期:从RD下降沿到下一次RD下降沿的最短时间。
  • 读写切换周期:从一次读操作结束到下一次写操作开始(或反之)的最短时间。

核心原则:所有时序参数都要满足LCD数据手册中的最小值。如果MCU速度太快,可以通过软件插入延时或调整GPIO翻转速度来降低速率。

3.4 时序参数速查表

下面这张表汇总了并行接口最常用的时序参数,建议你在设计时对照LCD的数据手册逐项核对:

符号 参数名称 方向 说明
tsu 数据建立时间 写 数据在WR上升沿前必须稳定
th 数据保持时间 写 数据在WR上升沿后必须保持
tWL WR低电平宽度 写 WR拉低的最短持续时间
tRL RD低电平宽度 读 RD拉低的最短持续时间
td 数据输出延迟 读 RD下降沿到数据有效的最大时间
tcyc 访问周期 读写 连续操作的最小间隔

3.5 时序知识结构图

下面这张SVG图帮你理清并行接口时序的核心脉络:

并行接口时序知识结构图 并行接口时序知识结构 并行接口时序 写操作时序 读操作时序 关键时序参数 CS/RS设置 数据建立 WR脉冲 数据保持 CS/RS设置 RD脉冲 数据输出 CPU读取 建立时间 保持时间 脉冲宽度 访问周期 核心:所有操作都必须满足建立时间、保持时间和访问周期的最小值要求

3.6 实战中的避坑指南

最后分享几个我踩过的坑,希望能帮你少走弯路:

  • 别只看典型值:数据手册里给的时序参数通常是“最小值”或“最大值”。我习惯在设计时留出20%~30%的余量,尤其是温度变化大的场合。
  • GPIO翻转速度:MCU的GPIO输出不是瞬间完成的。如果你用50MHz的STM32,GPIO翻转一次大约需要20ns。算时序时要把这个时间算进去。
  • 总线电容:如果LCD和MCU距离较远(比如通过排线连接),总线电容会增加信号上升时间。我曾经用了一根20cm的杜邦线,结果建立时间直接翻倍。
  • 读操作要小心:读时序中,LCD输出数据需要时间(td)。如果RD脉冲太短,CPU读到的是无效数据。我一般会在RD拉高后再等一个NOP才去读数据总线。

调试小技巧:如果你手头有逻辑分析仪,强烈建议抓一下实际的时序波形。把CS、RS、RD/WR、数据线都接上,看看实际波形和数据手册是否一致。很多时候,眼睛看到的“差不多”和实际需要的“精确”之间,差的就是那几十纳秒。