一、CSI是什么
CSI(Camera Serial Interface,相机串行接口)是业界广泛使用的相机接口协议,最初由MIPI联盟制定,全称是MIPI CSI-2。它专门用于把相机(图像传感器)和处理器(SoC、DSP、CPU等)之间的高速数据传输标准化。
简单说:CSI就是一根”数据高速公路”,让摄像头拍到的画面能高速、稳定地传进主控芯片。
二、CSI接口的技术特点
1. 物理层
- 差分信号:使用一对线传输数据(D+ / D-),抗干扰能力强
- Lane(通道):可以有1~4个Lane,每个Lane带宽很高(典型300Mbps~2Gbps)
- 电压低:通常1.2V~3.3V,功耗低
2. 协议层(CSI-2)
- 时钟信号:独立时钟线,接收端用时钟恢复数据
- 数据包格式:命令包、视频包、校验包等
- 错误检测:CRC校验,丢包可重传
- 多通道复用:支持多路相机同时接入
3. 典型速率
| Lane数 | 单Lane速率 | 总带宽 |
|---|---|---|
| 1 Lane | 1 Gbps | 1 Gbps |
| 2 Lanes | 1 Gbps | 2 Gbps |
| 4 Lanes | 1.5 Gbps | 6 Gbps |
三、CSI接口在设备通信中的使用场景
场景1:摄像头与嵌入式处理器通信(最常见)
硬件连接:
摄像头(Sensor)
│
├─ Lane0(数据0)──┐
├─ Lane1(数据1)──┤─→ FPC/排线 ──→ SoC(如NVIDIA Jetson、RK3588)
├─ Lane2(数据2)──┤
└─ Lane3(数据3)──┘
│
├─ 时钟线(Clock)
├─ 电源线(3.3V / 1.8V)
└─ I2C总线(控制传感器寄存器)
软件层面:
# 以NVIDIA Jetson为例,使用GStreamer通过CSI调用摄像头
import cv2
# CSI摄像头通常用GStreamer管道
pipeline = "nvarguscamerasrc ! video/x-raw(memory:NVMM),width=1920,height=1080,format=NV12 ! nvvidconv ! video/x-raw,width=1920,height=1080,format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink"
cap = cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow("CSI Camera", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
场景2:多摄像头同时通信
硬件拓扑:
CSI-2 Switch / Multiplexer
┌──────────┐
│ │
Camera0 ◄──────┤
Camera1 ◄──────┤──→ SoC (CSI Rx)
Camera2 ◄──────┤
Camera3 ◄──────┘
软件层面(ROS2 + CSI多摄):
# ROS2节点:读取CSI摄像头数据
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
class CSICameraNode(Node):
def __init__(self):
super().__init__('csi_camera_node')
self.bridge = CvBridge()
self.publisher = self.create_publisher(Image, 'csi_image', 10)
self.timer = self.create_timer(0.033, self.publish_image)
self.cap = cv2.VideoCapture(
"nvarguscamerasrc ! video/x-raw(memory:NVMM),width=1280,height=720 ! nvvidconv ! video/x-raw,format=BGR ! appsink",
cv2.CAP_GSTREAMER
)
def publish_image(self):
ret, frame = self.cap.read()
if ret:
msg = self.bridge.cv2_to_imgmsg(frame, encoding="bgr8")
self.publisher.publish(msg)
def main():
rclpy.init()
node = CSICameraNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
场景3:工业相机通信(Vision Pro / HALCON)
硬件连接(GigE + CSI混合架构):
工业相机(CMOS Sensor)
│
├─ CSI-2 接口 ──→ FPGA / ISP
│ │
│ 图像预处理
│ │
│ ┌─────┴─────┐
│ │ │
│ MIPI转并行 直接输出
│ │ │
│ CPU/DSP 高速存储
└──────────────────────────┘
使用HALCON读取CSI图像:
// HALCON:CSI相机图像处理
read_image(&Image, "csi_capture_001.png");
count_seconds(&StartTime);
// 图像处理
rgb1_to_gray(Image, &GrayImage);
threshold(GrayImage, &Regions, 128, 255);
connection(Regions, &ConnectedRegions);
select_shape(ConnectedRegions, &SelectedRegions, "area", "and", 1000, 99999);
area_center(SelectedRegions, &Area, &Row, &Column);
count_seconds(&EndTime);
Duration = EndTime - StartTime;
四、CSI设备通信的完整流程
步骤1:硬件连接
- 确认传感器支持CSI-2输出
- 使用FPC排线连接(注意防反插标识)
- 提供正确的电源(通常1.8V/2.8V/3.3V三档)
- 连接I2C总线用于传感器配置
步骤2:传感器驱动配置
// Linux设备树配置(以RK3588为例)
&i2c1 {
ov5647@36 {
compatible = "ovti,ov5647";
reg = <0x36>;
clocks = <&cruCLK_XTAL4>;
clock-names = "xclk";
port {
ov5647_ep: endpoint {
remote-endpoint = <&isp0_ep>;
data-lanes = <1 2>; // 2-Lane CSI
};
};
};
};
步骤3:应用程序调用
// V4L2接口读取CSI图像(通用Linux方式)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/videodevice.h>
int main() {
int fd = open("/dev/video0", O_RDWR);
if (fd < 0) {
perror("open video device");
return -1;
}
// 设置图像格式(1920x1080 RGB)
struct v4l2_format fmt = {0};
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
ioctl(fd, VIDIOC_S_FMT, &fmt);
// 申请缓冲区
struct v4l2_requestbuffers req = {0};
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd, VIDIOC_REQBUFS, &req);
// 开始采集
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd, VIDIOC_STREAMON, &type);
// 读取一帧
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl(fd, VIDIOC_DQBUF, &buf);
// 处理图像...
write_image(buf.m.vaddr, 1920, 1080);
ioctl(fd, VIDIOC_QBUF, &buf);
ioctl(fd, VIDIOC_STREAMOFF, &type);
close(fd);
return 0;
}
五、常见问题排查
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 画面花屏 | Lane接触不良 | 重新插拔FPC,检查针脚 |
| 无图像 | 驱动未加载 | 检查lsmod和dmesg |
| 图像偏色 | 色彩格式不匹配 | 确认V4L2 pixelformat |
| 帧率低 | 带宽不足 | 减少Lane数或降低分辨率 |
| 间歇性黑屏 | 电源不稳 | 增加滤波电容,检查电源 |
六、总结
CSI接口是摄像头与处理器之间的高速串行通信标准,核心要点:
- 物理层:差分信号,1~4 Lane,独立时钟
- 协议层:CSI-2数据包,CRC校验,支持多通道
- 软件调用:V4L2(Linux)、GStreamer(多平台)、ROS2(机器人)
- 典型应用:手机拍照、自动驾驶、工业检测、安防监控
使用CSI实现设备通信的关键:硬件连接正确 → 驱动配置正确 → 应用程序通过标准接口(V4L2/GStreamer)读取数据 → 图像处理。
