4、MIPI DSI协议:DSI命令模式与视频模式、DSI数据包格式(长包/短包)、DSI虚拟通道
MIPI DSI 协议,说白了就是屏幕和主控之间的“对话规则”。你想想看,一块显示屏要刷新画面,主控得把像素数据送过去。怎么送?什么时候送?送错了怎么办?这些都由 DSI 协议来管。
我个人习惯把 DSI 协议拆成三个维度来理解:传输模式(命令 vs 视频)、数据打包方式(长包 vs 短包)、通道复用(虚拟通道)。这三个维度搞清楚了,驱动移植时遇到的大部分问题都能找到根因。
4.1 命令模式 vs 视频模式:两种“说话”方式
DSI 定义了两种操作模式,区别在于谁控制刷新节奏。
| 特性 | 命令模式 | 视频模式 |
|---|---|---|
| 刷新控制方 | 主控发送命令,屏幕内部驱动 IC 自行刷新 | 主控实时发送像素流,屏幕被动接收 |
| 是否需要帧缓冲 | 屏幕端通常自带 GRAM(显存) | 屏幕端无显存,必须持续接收数据 |
| 典型应用 | 小尺寸屏(手表、IoT 设备) | 大尺寸屏(手机、平板、车载) |
| 功耗 | 低(可局部刷新、进入休眠) | 高(必须持续传输) |
| 实现复杂度 | 驱动端需要管理命令队列 | 驱动端需要精确时序同步 |
命令模式:主控发一条“写像素”命令,屏幕 IC 自己把数据存到内部 GRAM 里,然后按自己的节奏刷新。我在做智能手表驱动时遇到过一个问题——屏幕刷新率只有 30Hz,但主控发命令的速度远高于这个频率。结果呢?GRAM 写太快,屏幕读太慢,画面撕裂。解决办法是在命令之间插入 DCS Read 命令查询 TE(Tearing Effect)信号,等屏幕准备好再发下一帧。
视频模式:主控必须按行同步(HSYNC)和帧同步(VSYNC)的节奏,把像素数据一字节不差地送过去。屏幕没有缓存,你送慢了它就黑屏,送快了它就花屏。嗯,这里要注意:视频模式下 DSI 时钟必须和像素时钟严格匹配,差 1% 都不行。
关键判断依据:如果你的屏幕规格书里提到“GRAM”或“Frame Memory”,那多半是命令模式。如果只提“HSYNC/VSYNC/DE”时序参数,那就是视频模式。
4.2 DSI 数据包格式:长包与短包
DSI 协议里,所有数据都打包传输。包分两种:短包和长包。区别很简单——短包只有 4 字节,长包可以很长(最长 65541 字节)。
4.2.1 短包(Short Packet)
短包固定 4 字节:
字节 0: 数据标识符(DI, Data Identifier)
- bit[7:6]: 虚拟通道号(VC)
- bit[5:0]: 数据类型(DT)
字节 1: 数据低字节(Data Low)
字节 2: 数据高字节(Data High)
字节 3: 校验和(ECC, Error Correction Code)
短包用来干什么?发命令、读寄存器、设置参数。比如你想让屏幕进入休眠模式,发一个短包,数据类型设为 DCS Short Write,数据字节填 0x10(Sleep In 命令)。
我曾经踩过一个坑:ECC 校验位算错了。DSI 控制器硬件会自动计算 ECC,但如果你用 GPIO 模拟 DSI(有些低端 MCU 这么干),ECC 必须自己算。算错一个 bit,接收端直接丢弃包,屏幕没反应。我当时查了三天,最后用逻辑分析仪抓波形才发现 ECC 不对。
4.2.2 长包(Long Packet)
长包结构稍微复杂一点:
+----------------+----------------+------------------+------------------+----------------+
| 包首(4字节) | 数据负载 | 校验和(2字节) | 包尾 |
| DI + WC(2字节) + ECC | (0~65541字节) | (Checksum) | (停止状态) |
+----------------+----------------+------------------+------------------+----------------+
其中:
- DI:数据标识符,同短包
- WC(Word Count):数据负载的字节数,2 字节
- ECC:对包首 3 字节做校验
- 数据负载:真正的像素数据或命令参数
- Checksum:对数据负载做 16 位 CRC
长包用来传输大量数据,比如一帧图像、一块颜色查找表(LUT)。我建议你在驱动初始化时,用长包一次性把屏幕的初始化序列(Initial Code)发过去,比一条条发短包快得多。
实用技巧:长包的 Checksum 是可选的。如果你的 DSI 控制器硬件不支持自动计算 CRC,可以把 Checksum 设为 0x0000,接收端会忽略校验。但注意——这只适用于调试阶段,量产时一定要开校验。
4.3 DSI 虚拟通道:一条总线,多个设备
虚拟通道(Virtual Channel, VC)是 DSI 协议里一个很巧妙的设计。它允许在同一条物理 DSI 总线上,同时传输多个不同设备的数据。
VC 号占用 DI 字节的最高 2 个 bit,所以取值范围是 0~3,一共 4 个虚拟通道。
| VC 号 | 典型用途 | 示例 |
|---|---|---|
| VC0 | 主显示屏 | 手机主屏 |
| VC1 | 副显示屏 | 折叠屏的副屏 |
| VC2 | 触控数据 | 内嵌触控的显示面板 |
| VC3 | 调试/诊断 | 工厂测试模式 |
你想想看,如果一块屏幕同时要显示画面、接收触控数据、还要跑诊断命令,没有虚拟通道的话,你得拉三条物理 DSI 总线。有了 VC,一条总线就够了,接收端根据 VC 号把数据分发给不同的处理单元。
我在做双屏手机驱动时用过 VC。主屏用 VC0,副屏用 VC1,两个屏幕共用同一组 DSI 时钟和数据线。驱动里只需要在发送每个包之前设置好 VC 号,硬件自动把数据路由到对应的屏幕。嗯,这里有个坑:两个屏幕的时序参数可能不一样,切换 VC 时要注意重新配置 DSI 控制器的时序寄存器。
注意:虚拟通道只是逻辑上的复用,物理层仍然是同一组差分线。如果两个 VC 的数据速率加起来超过了 DSI 总线的最大带宽,就会出现丢包。我建议你在设计阶段就估算好总带宽,留出 20% 的余量。
4.4 三种模式的关系与选择
命令模式/视频模式、长包/短包、虚拟通道,这三者不是互斥的,而是可以组合使用的。比如:
- 视频模式下,像素数据用长包传输,配置命令用短包传输
- 命令模式下,写 GRAM 用长包,读状态用短包
- 虚拟通道可以在任何模式下使用
我一般这样选型:
- 低功耗、小尺寸 → 命令模式 + 短包为主 + VC0
- 高刷新率、大尺寸 → 视频模式 + 长包为主 + VC0~VC1
- 多设备复用 → 任意模式 + 合理分配 VC 号
最后说一句:DSI 协议看起来复杂,但实际驱动开发中,你只需要关注三件事——选对模式(看屏幕规格书)、打包正确(长包短包别搞混)、VC 别冲突(多设备时分配好)。剩下的,DSI 控制器硬件和驱动框架会帮你处理大部分细节。