3、传感器接口协议详解(下):SPI协议深度解析、MIPI CSI-2物理层介绍、DVP并行接口
好,咱们接着聊传感器接口。上一章我们把I2C和UART讲透了,这一章我重点说说SPI、MIPI CSI-2的物理层,还有那个看起来有点“复古”的DVP并行接口。这三个东西,在嵌入式视觉项目里你几乎天天要打交道。
3.1 SPI协议深度解析:不只是配置传感器
很多人觉得SPI就是用来配寄存器的,速度比I2C快一点而已。其实不然。我个人习惯把SPI看作一个“全双工的高速管道”,用好了能解决很多棘手问题。
3.1.1 四线还是三线?这是个问题
标准的SPI是四线制:SCLK、MOSI、MISO、CS。但我在项目中遇到过一种情况——传感器只支持三线半双工模式。说白了就是MOSI和MISO合并成一根线,分时复用。
嗯,这里要注意:如果你选的主控SPI外设不支持三线模式,那就得用GPIO模拟。我曾经在一个低功耗项目里这么干过,结果发现模拟出来的时序抖动太大,传感器偶尔会读出错误的数据。后来我换了一颗带三线SPI的MCU,问题才解决。
3.1.2 时钟极性和相位:别搞反了
SPI有四种模式,由CPOL(时钟极性)和CPHA(时钟相位)决定。你想想看,如果传感器手册里写的是“Mode 3”,而你配成了“Mode 0”,数据根本读不对。
我有个小技巧:拿到一个新传感器,先看它的时序图。找到SCLK的默认电平——高电平就是CPOL=1,低电平就是CPOL=0。然后再看数据是在SCLK的上升沿还是下降沿采样,这个决定了CPHA。
| 模式 | CPOL | CPHA | 采样沿 |
|---|---|---|---|
| Mode 0 | 0 | 0 | 上升沿 |
| Mode 1 | 0 | 1 | 下降沿 |
| Mode 2 | 1 | 0 | 上升沿 |
| Mode 3 | 1 | 1 | 下降沿 |
3.1.3 SPI速率:不是越快越好
SPI能跑到几十MHz,但传感器不一定扛得住。我记得有一次调试一个500万像素的传感器,SPI时钟设到20MHz,结果读出来的寄存器值偶尔会跳变。示波器一看,信号过冲严重,反射回来了。
为什么会这样?因为传感器那边的PCB走线太长,又没有端接电阻。我建议:SPI时钟超过10MHz时,尽量在靠近传感器端串一个22Ω或33Ω的电阻,能有效抑制振铃。
// SPI初始化示例(STM32 HAL库)
SPI_HandleTypeDef hspi1;
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL=0
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA=0
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; // 分频后约10MHz
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
3.2 MIPI CSI-2物理层介绍:高速串行的艺术
MIPI CSI-2是目前手机和嵌入式相机的主流接口。说白了,它就是用差分信号对来高速传输图像数据。物理层叫D-PHY,现在也有更新的C-PHY,但D-PHY还是最普及的。
3.2.1 差分信号:为什么抗干扰强?
D-PHY用一对线(DP和DN)传输一个信号。两个线上的电压是相反的,接收端看的是它们的差值。你想想看,如果外部噪声同时耦合到两根线上,差值基本不变——这就是共模抑制。
我在一个工业相机项目里遇到过强电磁干扰环境,用DVP接口的图像全是雪花点。换成MIPI CSI-2之后,画面干净得像没干扰一样。嗯,这就是差分信号的优势。
3.2.2 Lane数:1条还是4条?
MIPI CSI-2可以配置1条、2条或4条数据Lane,每条Lane都是差分对。带宽计算公式很简单:
总带宽 = Lane数 × 每Lane速率 × 编码效率
D-PHY用8B/10B编码,效率是80%。比如每Lane跑1Gbps,4条Lane就是4Gbps × 0.8 = 3.2Gbps的有效带宽。1080P 60fps的RAW10数据大概需要1.5Gbps,所以2条Lane就够了。
3.2.3 物理层布局:PCB走线是门学问
MIPI走线有几个硬性要求:
- 差分对内等长:误差控制在5mil以内
- 差分对间等长:误差控制在20mil以内
- 阻抗控制:100Ω差分阻抗,±10%
- 远离时钟源和电源:至少3倍线宽距离
我曾经在一个项目里忽略了等长要求,结果4条Lane的延时差太大,接收端数据对齐失败。后来重新画了一版PCB,把等长控制在5mil以内,问题才解决。嗯,这个坑我踩过,你们别踩了。
3.3 DVP并行接口:老兵不死,只是凋零
DVP(Digital Video Port)是传统的并行接口,用8位、10位或12位数据线同时传输像素数据。现在新传感器很少用了,但很多低成本的MCU和老的传感器还在用。
3.3.1 信号线一览
DVP接口的信号线包括:
- PCLK:像素时钟,每个时钟传输一个像素
- HSYNC:行同步信号,一行的开始
- VSYNC:帧同步信号,一帧的开始
- DATA[0:N]:并行数据线
说白了,DVP就是“一把梭”——所有数据同时传过来,简单粗暴。但缺点也很明显:信号线太多,容易受干扰,而且速率上不去。
3.3.2 时序要求:别小看同步信号
DVP的时序其实比MIPI更讲究。HSYNC和VSYNC的极性、前后肩、有效数据宽度,每个传感器都可能不一样。我建议拿到传感器手册后,先画一个时序图,把每个参数标清楚。
// DVP时序配置示例(假设传感器输出RAW8格式)
// VSYNC: 高电平有效,帧同步
// HSYNC: 高电平有效,行同步
// PCLK: 上升沿采样数据
void DVP_Init(void)
{
// 配置GPIO为复用功能
// 配置PCLK为输入,上升沿触发
// 配置VSYNC为输入,上升沿中断
// 配置HSYNC为输入,用于行计数
// 配置DATA[0:7]为输入
}
3.3.3 DVP vs MIPI:怎么选?
我个人的选择标准很简单:
- 分辨率低于VGA(640×480),帧率不高:DVP够用,成本低
- 分辨率在720P到1080P之间:DVP勉强能用,但建议上MIPI
- 分辨率超过1080P或帧率高于60fps:必须用MIPI
你想想看,DVP的PCLK跑到100MHz就已经很吃力了,而MIPI单条Lane就能跑1Gbps以上。所以,新项目我基本都推荐MIPI,除非主控不支持。
3.4 小结
这一章我们聊了SPI的深度用法、MIPI CSI-2的物理层要点,还有DVP并行接口的实战经验。SPI用来配寄存器,MIPI用来传图像,DVP则是老当益壮的备选方案。下一章我会讲传感器驱动开发的完整流程,从上电时序到图像输出,一步步带你走通。
嗯,今天就到这里。有什么问题,咱们课程群里聊。