3. EPD 硬件接口解析:SPI 接口时序、数据/命令控制、忙检测与复位时序
电子纸(EPD)显示驱动芯片与主控处理器之间的物理通信链路,是 FrameBuffer 驱动能够正常工作的硬件基础。本章将深入解析 EPD 硬件接口的四个核心要素:SPI 总线时序、数据/命令(D/C#)控制、忙检测(Busy)引脚以及复位(RST)时序。理解这些接口的电气特性和时序要求,是编写稳定、高效的 EPD 驱动的第一步。
3.1 EPD 硬件接口架构概览
典型的 EPD 模组与主控 SoC 之间的连接,通常包含以下信号线:
| 信号名称 | 方向 | 功能描述 |
|---|---|---|
| SCLK (SPI Clock) | 主控 → EPD | SPI 串行时钟,由主控提供,决定数据传输速率 |
| MOSI (Master Out Slave In) | 主控 → EPD | 主控输出数据线,用于发送命令和数据 |
| MISO (Master In Slave Out) | EPD → 主控 | 从设备输出数据线,部分 EPD 用于读取状态或寄存器 |
| CS# (Chip Select) | 主控 → EPD | 片选信号,低电平有效,选中 EPD 芯片进行通信 |
| D/C# (Data/Command) | 主控 → EPD | 数据/命令选择:高电平表示数据,低电平表示命令 |
| BUSY (Busy) | EPD → 主控 | 忙状态指示:高电平表示芯片正忙,低电平表示空闲 |
| RST# (Reset) | 主控 → EPD | 硬件复位信号,低电平有效,用于初始化芯片 |
接口选型提示: 大多数 EPD 驱动芯片(如 IT8951、SSD1680、UC8151)使用 3.3V 逻辑电平。与主控 SoC(如 1.8V 的 i.MX 或 RK 系列)连接时,必须使用电平转换器(如 TXS0108E)或确保 SoC 引脚兼容 3.3V 输入。
3.2 SPI 接口时序详解
EPD 驱动芯片通常支持 SPI Mode 0(CPOL=0, CPHA=0)或 SPI Mode 3(CPOL=1, CPHA=1)。在 Mode 0 下,时钟空闲时为低电平,数据在时钟上升沿采样;在 Mode 3 下,时钟空闲时为高电平,数据在时钟上升沿采样。绝大多数 EPD 驱动芯片默认使用 SPI Mode 0。
3.2.1 SPI 时序参数要求
不同 EPD 驱动芯片对 SPI 时钟频率和时序有严格要求。以下为常见芯片的典型参数:
| 参数 | 符号 | 最小值 | 典型值 | 最大值 | 单位 |
|---|---|---|---|---|---|
| SPI 时钟频率 | f_SCLK | - | 10 | 20 | MHz |
| 时钟高电平时间 | t_CLKH | 25 | 50 | - | ns |
| 时钟低电平时间 | t_CLKL | 25 | 50 | - | ns |
| CS# 建立时间 | t_CSS | 20 | 50 | - | ns |
| CS# 保持时间 | t_CSH | 20 | 50 | - | ns |
| 数据建立时间 | t_DSU | 10 | 20 | - | ns |
| 数据保持时间 | t_DHD | 10 | 20 | - | ns |
时序风险提示: 当主控 SoC 的 SPI 时钟频率超过 EPD 芯片的最大额定值时,可能导致数据采样错误、命令解析失败,甚至芯片锁死。建议在驱动初始化阶段,将 SPI 时钟配置为 10 MHz 或更低,待验证通信稳定后再逐步提高。
3.3 数据/命令控制(D/C# 引脚)
D/C# 引脚是 EPD 驱动芯片区分 SPI 总线上传输的是 命令 还是 数据 的关键信号。其逻辑电平定义如下:
- 低电平(0):表示当前 SPI 传输的是 命令(Command),例如初始化配置、寄存器写入、刷新触发等。
- 高电平(1):表示当前 SPI 传输的是 数据(Data),例如图像像素数据、查找表(LUT)内容等。
3.3.1 命令/数据发送流程
在驱动中,发送命令和数据的典型流程如下:
- 拉低 CS#:选中 EPD 芯片。
- 设置 D/C# 为低电平:指示接下来发送的是命令。
- 通过 SPI 发送命令字节:例如 0x01(软件复位)或 0x10(写入配置)。
- 设置 D/C# 为高电平:指示接下来发送的是数据。
- 通过 SPI 发送数据字节:例如配置参数或图像数据。
- 拉高 CS#:结束本次通信。
驱动实现示例: 在 Linux 内核驱动中,通常使用
gpiod_set_value() 控制 D/C# 引脚,使用 spi_write() 或 spi_write_then_read() 进行 SPI 数据传输。
/* 发送命令 */
static void epd_send_command(struct spi_device *spi, uint8_t cmd)
{
/* 设置 D/C# 为低电平(命令模式) */
gpiod_set_value(epd->dc_gpio, 0);
/* 发送命令字节 */
spi_write(spi, &cmd, 1);
}
/* 发送数据 */
static void epd_send_data(struct spi_device *spi, const uint8_t *data, size_t len)
{
/* 设置 D/C# 为高电平(数据模式) */
gpiod_set_value(epd->dc_gpio, 1);
/* 发送数据 */
spi_write(spi, data, len);
}
3.4 忙检测(Busy 引脚)
EPD 驱动芯片在执行内部操作(如刷新显示、初始化、查找表加载)时,会通过 BUSY 引脚向主控报告其工作状态。正确使用忙检测是防止驱动向芯片发送无效命令、避免通信冲突的关键。
3.4.1 Busy 引脚电平定义
| BUSY 电平 | 芯片状态 | 驱动行为 |
|---|---|---|
| 高电平(1) | 芯片正忙(Busy),正在执行内部操作 | 驱动应等待,不得发送新命令或数据 |
| 低电平(0) | 芯片空闲(Idle),可以接收新命令 | 驱动可以继续发送命令或数据 |
3.4.2 忙检测实现策略
在驱动中,忙检测通常采用 轮询(Polling) 或 中断(Interrupt) 两种方式:
- 轮询方式:在发送命令后,循环读取 BUSY 引脚电平,直到检测到低电平。适用于简单场景,但会占用 CPU。
- 中断方式:将 BUSY 引脚配置为上升沿/下降沿触发的中断,在中断处理函数中唤醒等待队列。效率更高,适合多任务系统。
轮询超时处理: 在轮询忙检测时,务必设置超时机制。例如,EPD 刷新操作可能持续 500ms 至 2s,如果超过 5s 仍未检测到空闲状态,应视为芯片异常,执行复位或报错。
/* 轮询等待芯片空闲,带超时 */
static int epd_wait_idle(struct epd_device *epd, unsigned long timeout_ms)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
while (time_before(jiffies, timeout)) {
if (gpiod_get_value(epd->busy_gpio) == 0) {
return 0; /* 芯片空闲 */
}
usleep_range(1000, 2000); /* 每 1-2ms 轮询一次 */
}
dev_err(&epd->spi->dev, "Busy wait timeout!\n");
return -ETIMEDOUT;
}
3.5 复位时序(RST# 引脚)
硬件复位是 EPD 驱动芯片初始化的第一步。正确的复位时序可以确保芯片内部状态机、寄存器和存储器处于已知的初始状态。
3.5.1 复位时序要求
典型的 EPD 复位时序包含以下步骤:
- 拉低 RST#:将复位引脚置为低电平,持续至少 10 µs(具体值参考芯片数据手册)。
- 保持低电平:确保芯片内部复位逻辑完成。
- 拉高 RST#:释放复位,芯片开始执行内部初始化。
- 等待初始化完成:通过 BUSY 引脚检测芯片是否进入空闲状态。
| 参数 | 符号 | 最小值 | 典型值 | 单位 |
|---|---|---|---|---|
| 复位低电平脉冲宽度 | t_RST_LOW | 10 | 50 | µs |
| 复位后等待时间 | t_RST_WAIT | 10 | 50 | ms |
| 初始化完成时间 | t_INIT | 100 | 500 | ms |
3.6 接口调试常见问题与排查
在 EPD 驱动开发过程中,硬件接口问题是最常见的故障来源。以下为典型问题及排查方法:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| SPI 通信无响应 | SCLK 极性/相位错误;CS# 未正确拉低;电平不匹配 | 使用逻辑分析仪抓取 SPI 波形,验证 Mode 0/3;检查电平转换 |
| 命令发送后芯片无反应 | D/C# 时序错误;复位不充分;芯片处于忙状态 | 检查 D/C# 电平切换时序;执行完整复位流程;等待 BUSY 释放 |