树莓派5刚发布那会儿,我第一时间入手了一块,冲着它那两个四通道MIPI接口去的。之前用树莓派4做视觉小车,CSI摄像头和DSI屏幕只能二选一,想同时接就得走HDMI或者SPI小屏,线缆一堆不说,刷新率和延迟都让人难受。树莓派5把MIPI接口从原来的一个拆成了两个独立的四通道收发器,理论上可以一个接CSI摄像头、一个接DSI屏幕,同时跑起来。但理论归理论,实际动手的时候,从排线选型到设备树配置,再到竖屏改横屏,我前后折腾了差不多三个晚上才彻底跑通。这篇文章就把整个过程中的关键决策、踩过的坑和最终稳定的配置方案完整梳理出来,给同样想在一台树莓派5上同时驱动摄像头和屏幕的朋友省点时间。
1. 先搞清楚树莓派5这两个MIPI口到底能干什么
1.1 两个接口的物理位置和通道分配
树莓派5板子上有两个FPC排线座,官方叫法是CAM/DISP 0和CAM/DISP 1。这两个口不是随便叫的,它们各自对应SoC内部一个独立的四通道MIPI收发器。注意关键词是“收发器”,意思是每个口既能发也能收,但同一时间只能选一个方向。你要接摄像头就是收,接屏幕就是发。
具体到物理位置,CAM/DISP 0在板子靠近USB-C供电口那一侧,CAM/DISP 1在靠近以太网口那一侧。两个座子都是22pin、0.5mm间距的FPC座,但针脚定义和树莓派4的15pin CSI口完全不同。这意味着你手里那些为树莓派4准备的摄像头排线,大概率插不上,需要买树莓派5专用的22pin转15pin排线,或者直接买原生22pin的摄像头模块。
我一开始就是吃了这个亏。手头有一个OV5647的老模块,配的是15pin排线,插到树莓派5上根本对不上。后来买了两根22pin转15pin的转接线才解决。这里提醒一句,转接线买的时候要看清方向,有些线是给DSI屏幕用的,针脚顺序和CSI的不一样,插错了轻则不亮,重则烧接口。
1.2 为什么不能两个口都接摄像头或者都接屏幕
这个问题我在论坛上看到不少人问。答案藏在SoC的MIPI控制器架构里。树莓派5的BCM2712有两个独立的MIPI D-PHY,每个PHY可以配置成CSI-2接收或者DSI发送,但不能同时。而且每个PHY只有四通道,如果你要接的摄像头是四通道的,那这个PHY就被占满了,另一个口虽然物理上存在,但内部资源已经分配完了。
实际配置的时候,设备树里会把CAM/DISP 0默认分配给CSI,CAM/DISP 1默认分配给DSI。如果你想反过来,比如摄像头接在1口、屏幕接在0口,是可以在config.txt里改的,但需要同时调整设备树覆盖层的加载顺序。我试过一次反过来接,结果屏幕能亮但摄像头死活不出图,后来查了半天发现是overlay的加载顺序冲突了。
提示:默认配置下,CAM/DISP 0走CSI,CAM/DISP 1走DSI。除非有特殊需求,建议按默认来,省去很多麻烦。
1.3 同时驱动时带宽和时钟的隐性约束
这是最容易被忽略的一点。MIPI CSI-2和DSI虽然物理层类似,但它们对时钟的要求不一样。CSI摄像头通常需要连续的时钟信号,而DSI屏幕在LP(低功耗)和HS(高速)模式之间切换时,时钟会间歇性停振。当两个接口同时工作时,如果时钟配置不当,会出现摄像头丢帧或者屏幕闪烁的问题。
我实测下来,OV5647在640x480@30fps下,四通道CSI的时钟大约在200MHz左右。而官方7寸DSI屏幕在800x480@60fps下,DSI时钟大约在300MHz。两个加起来对SoC的MIPI PLL压力不小。如果你用的是高分辨率摄像头或者高刷屏,建议先在单设备下测通,再同时接上,逐步排查。
2. 排线和接口选型:别在这上面省钱
2.1 22pin排线的线序陷阱
树莓派5的22pin MIPI座子,针脚定义里包含了I2C、GPIO和MIPI差分对。不同厂家出的22pin排线,线序可能不一样。我买过三根不同来源的线,有两根能用,一根插上后摄像头I2C能识别但不出图。后来用万用表量了一下,发现那根线的差分对正负接反了。
判断线序是否正确,最笨但最可靠的办法是看线的颜色和座子上的丝印。树莓派官方排线一般是同向的,即两端金手指在同一面。如果你买的是反向线,插上之前一定要确认哪一端接板子、哪一端接设备。接反了虽然不一定烧,但肯定不工作。
2.2 CSI摄像头模块的选择建议
如果你还没有摄像头,我建议直接买官方推荐的IMX219或者IMX477模块,原生22pin接口,省去转接的麻烦。OV5647虽然便宜,但它是老款,驱动支持虽然没问题,但在树莓派5上的自动曝光和白平衡调校不如IMX219稳定。
我手头有一个OV5647和一个IMX219,对比下来,IMX219在树莓派5上的出图速度更快,libcamera识别也更顺畅。如果你要做YOLOv5之类的目标检测,IMX219的1080p@30fps足够用了。OV5647最高只有1080p@30fps但实际跑下来帧率波动较大。
2.3 DSI屏幕的兼容性清单
DSI屏幕这块水比较深。官方7寸屏是最稳妥的选择,驱动直接集成在系统里,插上就能用。第三方屏幕就参差不齐了,有些需要自己编译设备树覆盖层,有些甚至要改内核驱动。
我试过一块第三方5寸DSI屏,卖家说支持树莓派5,结果插上后屏幕亮但花屏。后来查资料发现是它的初始化序列和官方屏不一样,需要在config.txt里加自定义的dsi参数。折腾了两天才搞定。所以如果你不想在驱动上花太多时间,官方屏是首选。
| 屏幕型号 | 分辨率 | 接口 | 树莓派5兼容性 | 备注 |
|---|---|---|---|---|
| 官方7寸DSI | 800x480 | 22pin DSI | 原生支持 | 最省心 |
| 官方7寸DSI | 800x480 | 15pin DSI | 需转接线 | 转接后可用 |
| 第三方5寸DSI | 800x480 | 22pin DSI | 需调参 | 可能花屏 |
| 第三方10寸DSI | 1280x800 | 22pin DSI | 需编译overlay | 难度较高 |
3. 系统配置:从config.txt到设备树覆盖层
3.1 基础系统准备和更新
拿到树莓派5后,第一件事是用官方Imager烧录最新的Raspberry Pi OS Bookworm。注意一定要用Bookworm或更新版本,Bullseye对树莓派5的MIPI支持不完整。烧录完成后,先别急着接摄像头和屏幕,先通过SSH或者HDMI开机,把系统更新到最新。
sudo apt update sudo apt full-upgrade -y sudo reboot更新完成后,检查一下内核版本。树莓派5的MIPI驱动在6.1.x之后才比较稳定。用uname -a看一下,如果内核低于6.1,建议手动升级。
3.2 config.txt里必须加的那几行
树莓派5的config.txt在/boot/firmware/目录下,不是以前的/boot/。这一点很多人会搞错。打开后,你需要根据实际接线来配置。
如果摄像头接在CAM/DISP 0,屏幕接在CAM/DISP 1,config.txt里需要加:
dtoverlay=imx219,cam0 dtoverlay=vc4-kms-dsi-7inch第一行是加载IMX219的CSI覆盖层,指定cam0。第二行是加载官方7寸DSI屏幕的覆盖层。注意顺序不能反,先CSI后DSI。我试过反过来写,结果屏幕能亮但摄像头不出图。
如果你用的是OV5647,把imx219换成ov5647即可。但OV5647在树莓派5上需要额外的media-controller参数,具体后面会讲。
3.3 设备树覆盖层的加载顺序为什么重要
设备树覆盖层本质上是往内核设备树里打补丁。每个覆盖层会申请MIPI控制器资源。如果DSI覆盖层先加载,它会把CAM/DISP 1的PHY配置成发送模式,然后CSI覆盖层再去申请CAM/DISP 0的PHY,这时候如果资源分配有冲突,CSI就会失败。
我遇到过一次,config.txt里DSI写在前面,结果dmesg里看到csi: probe failed with error -22。把顺序调换后问题消失。所以记住一个原则:先加载接收端(CSI),再加载发送端(DSI)。
3.4 验证设备是否被正确识别
配置完成后重启,用以下命令检查:
libcamera-hello --list-cameras如果摄像头被识别,会列出可用的摄像头和分辨率。如果没识别到,检查排线是否插紧、config.txt是否正确。
对于DSI屏幕,用:
dmesg | grep dsi看有没有dsi相关的报错。如果屏幕亮但没显示,可能是KMS驱动没加载,检查/boot/firmware/config.txt里有没有dtoverlay=vc4-kms-v3d。
4. 竖屏改横屏:DSI显示方向的完整调整方案
4.1 为什么竖屏改横屏不是简单旋转一下
DSI屏幕默认是竖屏输出,但很多人做监控或者车载显示需要横屏。在树莓派上,旋转屏幕有两种方式:一种是在config.txt里加display_rotate,另一种是在桌面环境里用xrandr。但DSI屏幕比较特殊,display_rotate对KMS驱动无效,需要用dtoverlay里的rotate参数。
官方7寸DSI屏的覆盖层支持rotate参数,取值0、90、180、270。比如要旋转90度:
dtoverlay=vc4-kms-dsi-7inch,rotate=90但注意,旋转后触摸坐标不会自动跟着转。如果你用的是官方触摸屏,还需要在/etc/udev/rules.d/里加触摸校准规则。我一开始只转了显示,结果触摸完全对不上,点左边触发右边,折腾了好久才发现是触摸矩阵没转。
4.2 触摸坐标的同步旋转
对于官方7寸触摸屏,创建一个文件/etc/udev/rules.d/99-touchscreen.rules,内容如下:
ACTION=="add", SUBSYSTEM=="input", ATTRS{name}=="raspberrypi-ts", ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1"这组矩阵对应90度旋转。如果是180度,矩阵是-1 0 1 0 -1 1。270度是0 -1 1 1 0 0。改完后重启,触摸就正常了。
4.3 横屏后的分辨率适配问题
旋转90度后,原本800x480的屏幕变成480x800的逻辑分辨率。如果你跑桌面环境,图标和文字会变得很大。这时候需要在/boot/firmware/cmdline.txt里加fbcon=rotate:1,让控制台也跟着转。但桌面环境的旋转需要在Screen Configuration里手动设置。
我实测下来,如果只是跑Python OpenCV显示摄像头画面,直接用cv2.imshow全屏,旋转由代码里的cv2.rotate处理更简单,不用折腾系统层旋转。这样屏幕保持竖屏物理方向,但画面内容旋转90度,效果一样。
5. 同时驱动时的资源冲突与排查实录
5.1 摄像头出图但屏幕黑屏的排查过程
这是我遇到的第一个大坑。config.txt配好后,libcamera-hello能出图,但DSI屏幕一直黑。dmesg里看到vc4-dsi: failed to allocate dma buffer。查了半天,发现是GPU内存分配不够。
树莓派5默认的GPU内存是76MB,同时驱动CSI和DSI时不够用。需要在config.txt里加:
gpu_mem=128或者更高,比如256。改完后重启,屏幕就亮了。这个参数在树莓派4上很少需要改,但树莓派5的MIPI双开对内存需求更大。
5.2 屏幕亮了但摄像头掉帧的解决
屏幕点亮后,我发现摄像头帧率从30fps掉到了15fps左右。用top看CPU占用不高,但v4l2-ctl显示有丢帧。后来查资料发现是MIPI时钟冲突。CSI和DSI共用同一个PLL,如果DSI的时钟配置得太高,CSI的时钟就会被压缩。
解决办法是在config.txt里给DSI屏幕降刷新率。官方7寸屏默认60Hz,改成50Hz:
dtoverlay=vc4-kms-dsi-7inch,refresh=50改完后摄像头帧率恢复到28fps左右,屏幕也没有明显闪烁。如果你用的是第三方屏,可能需要手动调dsi_timing参数,这个比较复杂,建议先试降刷新率。
5.3 I2C地址冲突的隐蔽问题
还有一个不容易发现的问题:摄像头和触摸屏都可能走I2C。OV5647的I2C地址是0x36,官方7寸触摸屏的地址是0x38,理论上不冲突。但如果你用的第三方触摸屏地址也是0x36,就会冲突。
排查方法是:
i2cdetect -y 10树莓派5的MIPI I2C总线是i2c-10和i2c-11。如果看到两个设备地址一样,就需要改其中一个的地址,或者换一个触摸屏。
6. 跑通之后的实战:用OpenCV同时采集和显示
6.1 安装OpenCV和必要的依赖
系统跑通后,装OpenCV:
sudo apt install python3-opencv -y如果你要用YOLOv5,还需要装PyTorch。但树莓派5上装PyTorch比较慢,建议用预编译的wheel或者直接跑ONNX Runtime。
6.2 一个同时采集和显示的Python脚本
下面这个脚本是我实际在用的,摄像头采集画面,经过简单处理后全屏显示在DSI屏幕上:
import cv2 import numpy as np # 打开摄像头,树莓派5上libcamera的索引通常是0 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 创建全屏窗口 cv2.namedWindow("Display", cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty("Display", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) while True: ret, frame = cap.read() if not ret: break # 如果屏幕是竖屏物理方向,旋转90度 frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) # 显示 cv2.imshow("Display", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()这个脚本跑下来,640x480@30fps很稳,CPU占用在40%左右。如果你要跑YOLOv5,建议把分辨率降到320x320,帧率能保持在15fps以上。
6.3 长时间运行的稳定性观察
我连续跑了48小时,中间没有重启。观察到的现象是:前24小时很稳定,24小时后摄像头偶尔会丢一帧,屏幕没有闪烁。查了一下,可能是内存碎片导致的。建议长时间运行时,每隔几小时重启一次摄像头采集,或者用v4l2-ctl重新初始化。
另外,树莓派5的发热比4代大,同时跑CSI和DSI时,SoC温度在70度左右。建议加散热片或者小风扇,否则温度到80度以上会降频,摄像头帧率会明显下降。
7. 几个容易被忽略的细节和我的个人建议
7.1 供电不足会导致MIPI接口不稳定
树莓派5需要5V/5A的供电,官方电源是27W。如果你用普通的5V/3A电源,同时接摄像头和屏幕时,可能会出现屏幕闪烁或者摄像头识别失败。我一开始用的是一个旧手机的充电器,结果屏幕一直闪,换了官方电源后问题消失。所以别在电源上省钱。
7.2 排线长度对信号质量的影响
MIPI是高速差分信号,排线太长会导致信号衰减。官方排线一般是15cm左右,如果你需要更长的,建议不要超过30cm。我试过用一根50cm的排线,结果摄像头直接不识别。后来换成20cm的,一切正常。
7.3 系统升级后配置可能被覆盖
Raspberry Pi OS的大版本升级有时会重置config.txt。我有一次升级后,发现摄像头和屏幕都不工作了,检查后发现config.txt被恢复成了默认值。所以升级前最好备份一下config.txt,升级后对比一下。
7.4 关于YOLOv5部署的额外提醒
如果你打算在这套配置上跑YOLOv5,建议用ONNX Runtime而不是PyTorch。PyTorch在树莓派5上安装麻烦,而且推理速度不如ONNX。我实测下来,YOLOv5s在640x640输入下,ONNX Runtime能跑到8fps左右,PyTorch只有4fps。另外,摄像头采集和推理最好分线程处理,否则显示会卡顿。
7.5 最后分享一个排查小技巧
当你遇到摄像头或屏幕不工作时,先别急着改配置。用以下命令看一下内核日志:
dmesg | grep -E "csi|dsi|mipi"大部分问题都能从这里找到线索。比如probe failed通常是设备树配置问题,dma buffer是内存问题,i2c timeout是排线或地址问题。根据报错去搜,比盲目试错快得多。
这套配置我目前已经稳定用了两个月,每天跑8小时以上,没有出现过掉线或者花屏。如果你也在树莓派5上折腾双MIPI,希望这篇记录能帮你少走点弯路。