一、硬件原理
1. OV2640
1.1 基本功能
OV2640 是一款低功耗、高性能的图像传感器,支持以下功能:
-
最高分辨率:200 万像素(1600x1200)。
-
输出格式:JPEG、YUV、RGB。
-
内置图像处理功能:自动曝光、自动白平衡、自动增益控制等。
1.2 硬件接口


2. CSI
2.1 基本功能
CSI 是一种高速串行接口,专为摄像头模块设计,具有以下特点:
-
支持高带宽数据传输(适合高分辨率和高帧率视频)。
-
低引脚数,减少硬件复杂度。
-
支持多种数据格式(如 RAW、YUV、RGB)。
2.2 硬件原理
CSI 接口通常包括以下信号:
-
数据通道(Data Lanes):
-
差分信号对(如 CSI_D0+/CSI_D0-)。
-
支持 1-4 对数据通道,带宽随通道数增加。
-
-
时钟通道(Clock Lane):
-
差分信号对(如 CSI_CLK+/CSI_CLK-)。
-
用于同步数据传输。
-
-
控制信号:
- I2C 或 SPI 接口,用于配置摄像头模块。
2.3 工作流程
-
初始化:通过 I2C 或 SPI 配置摄像头模块。
-
数据传输:
-
摄像头模块通过 CSI 数据通道发送图像数据。
-
主控设备通过 CSI 时钟通道同步接收数据。
-
-
数据处理:主控设备对接收到的图像数据进行处理或存储。

二、设备树
根节点
&csi {
status = "okay";
port {
csi1_ep: endpoint {
remote-endpoint = <&ov2640_ep>;
};
};
};
&i2c1 {
ov2640: ov2640@30 {
compatible = "ovti,ov2640";
reg = <0x30>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_csi1>;
clocks = <&clks IMX6UL_CLK_CSI>;
clock-names = "csi_mclk";
/*pwn-gpios = <&gpio1 4 1>;*/
rst-gpios = <&gpio1 2 0>;
/*csi_id = <0>;
mclk = <24000000>;
mclk_source = <0>;*/
status = "okay";
port {
ov2640_ep: endpoint {
remote-endpoint = <&csi1_ep>;
};
};
};
};
三、驱动简单分析
四、Qt 编写测试文件
1. 简介
Qt 里有一个 QCamera 类,但是不支持4.1.15 内核版本上使用 OV5640、OV2640。
因为 OV5640、OV2640 的驱动默认是读取 YUYV 格式数据,而 QCamera 里读取的数据是 RGB 格式数据。当然也能通过修改驱动来支持。不过有 V4l2 框架,就没必要这么做了。V4l2 的数据直接可以显示在 fb0,且处理效率比 Qt 来的流程。
直接使用 V4l2 的方案留在后面的视频监控项目上。本次使用的是 Qt+OpenCV 调用摄像头。
OpenCV 的环境搭建:ARM Linux 移植 tslib、Qt和OpenCV-CSDN博客
2. 主要功能
-
摄像头管理
selectCameraDevice(int index)
:选择并打开指定索引的摄像头cameraProcess(bool bl)
:控制摄像头的启动和停止timerTimeOut()
:定时采集摄像头图像并发送信号
-
图像处理
matToQImage(const cv::Mat &img)
:将 OpenCVcv::Mat
格式转换为 QtQImage
格式
-
定时器机制
- 使用
QTimer
控制图像采集频率(33ms,约等于 30fps)
- 使用
3. 程序编写
3.1 .pro 文件
添加 opencv 库
cpp
INCLUDEPATH += /home/prover/linux/opencv-3.4.1/install/include
LIBS += /home/prover/linux/opencv-3.4.1/install/lib/libopencv_core.so \
/home/prover/linux/opencv-3.4.1/install/lib/libopencv_highgui.so \
/home/prover/linux/opencv-3.4.1/install/lib/libopencv_imgproc.so \
/home/prover/linux/opencv-3.4.1/install/lib/libopencv_videoio.so \
/home/prover/linux/opencv-3.4.1/install/lib/libopencv_imgcodecs.so
3.2 简单分析

3.3 编译
cpp
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
/home/prover/linux/qt-5.12.9/arm-qt/bin/qmake
make -j 8
五、测试
1. 手动加载
将内核源码的drivers/media/paltform/mxc/subdev 中的mx6s_capture.c 单独拿出来编译 .ko文件
然后将 ov2640_driver.ko 和 mx6s_capture.ko 文件进行加载即可。
一般加载后,设备为 /dev/video1。然后运行第四节的 Qt 程序即可。
2. 内核修改

配置 4.1.15 内核
按1进入

按Y选中,并进入红框

红框默认是 M 的,改成 Y,并选择 VF SDC。
还有这个也要选中:

如果不出意外的话,就会出意外了:
修改内核源码中的 drivers/media/platform/mxc/capture/ 下的 ipu_prp_vf_sdc.c和ipu_prp_vf_sdc_bg.c
重新编译下内核。

发现取消绑定了。
然后加载自己写的驱动,当然也可以编入到内核的 drivers/media/paltform/mxc/capture:

运行测试前,可以添加格式:drivers\media\platform\mxc\subdev\mx6s_capture.c
static struct mx6s_fmt formats[] = {
{
.name = "UYVY-16",
.fourcc = V4L2_PIX_FMT_UYVY,
.pixelformat = V4L2_PIX_FMT_UYVY,
.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
.bpp = 2,
}, {
.name = "YUYV-16",
.fourcc = V4L2_PIX_FMT_YUYV,
.pixelformat = V4L2_PIX_FMT_YUYV,
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.bpp = 2,
}, {
.name = "YUV32 (X-Y-U-V)",
.fourcc = V4L2_PIX_FMT_YUV32,
.pixelformat = V4L2_PIX_FMT_YUV32,
.mbus_code = MEDIA_BUS_FMT_AYUV8_1X32,
.bpp = 4,
}, {
.name = "RAWRGB8 (SBGGR8)",
.fourcc = V4L2_PIX_FMT_SBGGR8,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
.bpp = 1,
}, {
.name = "RGB565_LE",
.fourcc = V4L2_PIX_FMT_RGB565,
.pixelformat = V4L2_PIX_FMT_RGB565,
.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
.bpp = 2,
}, {
.name = "RGB565_BE",
.fourcc = V4L2_PIX_FMT_RGB565,
.pixelformat = V4L2_PIX_FMT_RGB565,
.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_BE,
.bpp = 2,
}, {
.name = "JPEG",
.fourcc = V4L2_PIX_FMT_JPEG,
.pixelformat = V4L2_PIX_FMT_JPEG,
.mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
.bpp = 2,
}
};
一般加载后,设备为 /dev/video0.
然后运行第四节的 Qt 程序即可。