作者共發了14篇帖子。 字體大小:較小 - 100% (默認)▼  內容轉換:不轉換▼
 
點擊 回復
45 13
瑞芯微RV1106通过MIPI CSI-2 D-PHY接口驱动OV5640摄像头并拍摄照片
一派掌門 二十級
1樓 發表于:2025-6-17 17:56

一派掌門 二十級
2樓 發表于:2025-6-17 17:59

【sysdrv\source\kernel\arch\arm\boot\dts\rv1106-luckfox-pico-pro-max-ipc.dtsi】

csi_dphy_input0: endpoint@0里面,将remote-endpoint = <&sc3336_out>;改成remote-endpoint = <&ov5640_out>;

&i2c4里面的最后添加:
    ov5640: ov5640@3c {
        compatible = "ovti,ov5640";
        status = "okay";
        reg = <0x3c>;
        clocks = <&cru MCLK_REF_MIPI0>;
        clock-names = "xclk";
        reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>;
        pinctrl-names = "default";
        pinctrl-0 = <&mipi_refclk_out0>;
        port {
            ov5640_out: endpoint {
                remote-endpoint = <&csi_dphy_input0>;
                clock-lanes = <0>;
                data-lanes = <1 2>;
            };
        };
    };

 
一派掌門 二十級
3樓 發表于:2025-6-17 18:00

【sysdrv\source\kernel\arch\arm\configs\luckfox_rv1106_linux_defconfig】

在CONFIG_VIDEO_RK_IRCUT=y下方添加CONFIG_VIDEO_OV5640=y

 
一派掌門 二十級
4樓 發表于:2025-6-17 18:04

【sysdrv\source\kernel\drivers\media\i2c\ov5640.c】

包含头文件:

#include <linux/rk-camera-module.h>

 

ov5640_init_controls里面:

static int ov5640_init_controls(struct ov5640_dev *sensor)
{
 const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
 struct ov5640_ctrls *ctrls = &sensor->ctrls;
 struct v4l2_ctrl_handler *hdl = &ctrls->handler;
 int ret;

********************************添加内容开始**************************************************

#define SC3336_LINK_FREQ_253  253125000
#define SC3336_LINK_FREQ_255  255000000
 static const s64 link_freq_menu_items[] = {SC3336_LINK_FREQ_253, SC3336_LINK_FREQ_255};
 struct v4l2_ctrl *link_freq;

********************************添加内容结束**************************************************

 v4l2_ctrl_handler_init(hdl, 32);

 /* we can use our own mutex for the ctrl lock */
 hdl->lock = &sensor->lock;

********************************添加内容开始**************************************************

 link_freq = v4l2_ctrl_new_int_menu(hdl, NULL,
   V4L2_CID_LINK_FREQ,
   ARRAY_SIZE(link_freq_menu_items) - 1, 0, link_freq_menu_items);
 if (link_freq != NULL)
  link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
********************************添加内容结束**************************************************

 

添加ov5640_ioctl函数:

static long ov5640_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
 struct ov5640_dev *sensor = to_ov5640_dev(sd);
 struct rkmodule_channel_info *ch_info;
 long ret = 0;

 switch (cmd) {
 case RKMODULE_GET_CHANNEL_INFO:
  ch_info = (struct rkmodule_channel_info *)arg;
  ch_info->width = ov5640_mode_data[OV5640_NUM_MODES - 1].hact;
  ch_info->height = ov5640_mode_data[OV5640_NUM_MODES - 1].vact;
  ch_info->bus_fmt = sensor->fmt.code;
  break;
 default:
  ret = -ENOIOCTLCMD;
  break;
 }

 return ret;
}

 

static const struct v4l2_subdev_core_ops ov5640_core_ops里面添加.ioctl = ov5640_ioctl,

 
一派掌門 二十級
5樓 發表于:2025-6-17 18:05

添加ov5640_mbus_config函数:

#define OV5640_LANES 2
static int ov5640_mbus_config(struct v4l2_subdev *sd,
    unsigned int pad_id,
    struct v4l2_mbus_config *config)
{
 config->type = V4L2_MBUS_CSI2_DPHY;
 config->flags = 1 << (OV5640_LANES - 1) |
  V4L2_MBUS_CSI2_CHANNEL_0 |
  V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;

 return 0;
}

 

static const struct v4l2_subdev_pad_ops ov5640_pad_ops里面添加.get_mbus_config = ov5640_mbus_config,

 
一派掌門 二十級
6樓 發表于:2025-6-17 18:08

【sysdrv\source\kernel\drivers\media\platform\rockchip\cif\mipi-csi2.c】
添加函数:
static int csi2_g_frame_interval(struct v4l2_subdev *sd,
         struct v4l2_subdev_frame_interval *fi)
{
 struct v4l2_subdev *sensor = get_remote_sensor(sd);

 if (sensor)
  return v4l2_subdev_call(sensor, video, g_frame_interval, fi);

 return -EINVAL;
}

static int csi2_s_frame_interval(struct v4l2_subdev *sd,
         struct v4l2_subdev_frame_interval *fi)
{
 struct v4l2_subdev *sensor = get_remote_sensor(sd);

 if (sensor)
  return v4l2_subdev_call(sensor, video, s_frame_interval, fi);

 return -EINVAL;
}

 

static int csi2_get_set_fmt(struct v4l2_subdev *sd,改成static int csi2_get_fmt(struct v4l2_subdev *sd,
然后在下面添加csi2_set_fmt函数:
static int csi2_set_fmt(struct v4l2_subdev *sd,
       struct v4l2_subdev_pad_config *cfg,
       struct v4l2_subdev_format *fmt)
{
 int ret;
 struct csi2_dev *csi2 = sd_to_dev(sd);
 struct v4l2_subdev *sensor = get_remote_sensor(sd);
 
 ret = v4l2_subdev_call(sensor, pad, set_fmt, NULL, fmt);
 if (!ret)
  csi2->format_mbus = fmt->format;

 return ret;
}

 

static const struct v4l2_subdev_video_ops csi2_video_ops添加:
 .g_frame_interval = csi2_g_frame_interval,
 .s_frame_interval = csi2_s_frame_interval,
 
static const struct v4l2_subdev_pad_ops csi2_pad_ops添加:
 .get_fmt = csi2_get_fmt,
 .set_fmt = csi2_set_fmt,

 
一派掌門 二十級
7樓 發表于:2025-6-17 18:11

【sysdrv\source\kernel\drivers\phy\rockchip\phy-rockchip-csi2-dphy.c】
在csi2_dphy_g_frame_interval函数下面添加函数:
static int csi2_dphy_s_frame_interval(struct v4l2_subdev *sd,
         struct v4l2_subdev_frame_interval *fi)
{
 struct v4l2_subdev *sensor = get_remote_sensor(sd);

 if (sensor)
  return v4l2_subdev_call(sensor, video, s_frame_interval, fi);

 return -EINVAL;
}

 

static int csi2_dphy_get_set_fmt(struct v4l2_subdev *sd,改成static int csi2_dphy_get_fmt(struct v4l2_subdev *sd,
并在下面添加
static int csi2_dphy_set_fmt(struct v4l2_subdev *sd,
    struct v4l2_subdev_pad_config *cfg,
    struct v4l2_subdev_format *fmt)
{
 struct csi2_dphy *dphy = to_csi2_dphy(sd);
 struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
 struct csi2_sensor *sensor;
 int ret;
 if (!sensor_sd)
  return -ENODEV;
 sensor = sd_to_sensor(dphy, sensor_sd);
 if (!sensor)
  return -ENODEV;
 ret = v4l2_subdev_call(sensor_sd, pad, set_fmt, NULL, fmt);
 if (!ret && fmt->pad == 0 && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
  sensor->format = fmt->format;
 return ret;
}

 

static const struct v4l2_subdev_video_ops csi2_dphy_video_ops添加
 .s_frame_interval = csi2_dphy_s_frame_interval,
 
static const struct v4l2_subdev_pad_ops csi2_dphy_subdev_pad_ops里面修改
 .set_fmt = csi2_dphy_set_fmt,
 .get_fmt = csi2_dphy_get_fmt,

 
一派掌門 二十級
8樓 發表于:2025-6-17 18:11

【拍照程序:test\ov5640\ov5640.c】

#include <fcntl.h>
#include <linux/v4l2-subdev.h>
#include <linux/videodev2.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "bmp.h"

int yuv2rgb(int y, int u, int v, uint8_t *_r, uint8_t *_g, uint8_t *_b)
{
 int r, g, b;
 
 // https://blog.csdn.net/u012294613/article/details/141095964
 r = y + 1403 * (v - 128) / 1000;
 g = y - 343 * (u - 128) / 1000 - 714 * (v - 128) / 1000;
 b = y + 1770 * (u - 128) / 1000;

 if (r > 255)
  r = 255;
 else if (r < 0)
  r = 0;
 
 if (g > 255)
  g = 255;
 else if (g < 0)
  g = 0;
 
 if (b > 255)
  b = 255;
 else if (b < 0)
  b = 0;
 
 *_r = (uint8_t)r;
 *_g = (uint8_t)g;
 *_b = (uint8_t)b;
 return (r << 16) | (g << 8) | b;
}

void convert_to_bitmap(const uint8_t *data, long size, const char *filename, int width, int height)
{
 int bmpsize, stride;
 int i, j, m, n;
 int y1, u, y2, v;
 uint8_t *bmpdata;
 BITMAPFILEHEADER bmpfilehdr = {0};
 BITMAPINFOHEADER bmphdr = {0};
 FILE *fp;

 fp = fopen(filename, "wb");
 if (fp == NULL)
  return;

 memcpy(&bmpfilehdr.bfType, "BM", 2);
 bmpfilehdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

 bmphdr.biSize = sizeof(BITMAPINFOHEADER);
 bmphdr.biWidth = width;
 bmphdr.biHeight = -height;
 bmphdr.biPlanes = 1;
 bmphdr.biBitCount = 24;
 bmphdr.biCompression = BI_RGB;

 stride = ((((width * bmphdr.biBitCount) + 31) & ~31) >> 3);
 bmpsize = height * stride;
 bmpfilehdr.bfSize = bmpfilehdr.bfOffBits + bmpsize;
 fwrite(&bmpfilehdr, sizeof(BITMAPFILEHEADER), 1, fp);
 fwrite(&bmphdr, bmphdr.biSize, 1, fp);

 bmpdata = malloc(bmpsize);
 if (bmpdata != NULL)
 {
  m = 0;
  n = 0;
  for (i = 0; i < height; i++)
  {
   for (j = 0; j < width; j += 2)
   {
    if (m + 4 > size)
     break;

    y1 = data[m];
    u = data[m + 1];
    y2 = data[m + 2];
    v = data[m + 3];
    yuv2rgb(y1, u, v, &bmpdata[n + j * 3 + 2], &bmpdata[n + j * 3 + 1], &bmpdata[n + j * 3]);
    yuv2rgb(y2, u, v, &bmpdata[n + j * 3 + 5], &bmpdata[n + j * 3 + 4], &bmpdata[n + j * 3 + 3]);
    m += 4;
   }
   n += stride;
  }

  fwrite(bmpdata, 1, bmpsize, fp);
  free(bmpdata);
 }

 fclose(fp);
}

int main()
{
 char filename[50];
 int fd;
 int i, ret;
 struct v4l2_subdev_frame_interval subdev_interval;
 struct v4l2_subdev_format subdev_format;
 struct v4l2_capability cap;
 struct v4l2_fmtdesc fmtdesc;
 struct v4l2_format format;
 struct v4l2_requestbuffers reqbufs;
 struct v4l2_buffer buf;
 struct v4l2_plane plane;
 unsigned char *mem[4];
 unsigned int memsize[4];
 
 system("rm *.bin *.bmp photos/*.bmp 2>/dev/null");
 
 fd = open("/dev/v4l-subdev0", O_RDWR);
 if (fd == -1)
 {
  printf("failed to open /dev/v4l-subdev0\n");
  return -1;
 }
 
 subdev_interval.interval.numerator = 1;
 subdev_interval.interval.denominator = 15;
 subdev_interval.pad = 0;
 ret = ioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &subdev_interval);
 if (ret == -1)
  printf("VIDIOC_SUBDEV_S_FRAME_INTERVAL failed\n");
 else
  printf("interval=%d/%d\n", subdev_interval.interval.numerator, subdev_interval.interval.denominator);
 
 subdev_format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 subdev_format.pad = 0;
 ret = ioctl(fd, VIDIOC_SUBDEV_G_FMT, &subdev_format);
 if (ret == -1)
  printf("VIDIOC_SUBDEV_G_FMT failed\n");
 else
  printf("code=0x%x, field=%d\n", subdev_format.format.code, subdev_format.format.field);
 
 subdev_format.format.width = 2592;
 subdev_format.format.height = 1944;
 ret = ioctl(fd, VIDIOC_SUBDEV_S_FMT, &subdev_format);
 if (ret == -1)
  printf("VIDIOC_SUBDEV_S_FMT failed\n");
 close(fd);

 fd = open("/dev/video0", O_RDWR);
 if (fd == -1)
 {
  printf("failed to open /dev/video0\n");
  return -1;
 }

 ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
 if (ret == -1)
  printf("VIDIOC_QUERYCAP failed\n");
 else
 {
  printf("Driver: %s\n", cap.driver);
  printf("Card: %s\n", cap.card);
  printf("Bus info: %s\n", cap.bus_info);
  printf("Version: %d\n", cap.version);
 }

 printf("VIDIOC_ENUM_FMT start\n");
 fmtdesc.index = 0;
 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)
 {
  printf("\t%d.%s\n", fmtdesc.index + 1, fmtdesc.description);
  fmtdesc.index++;
 }
 printf("VIDIOC_ENUM_FMT end\n");

 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 format.fmt.pix_mp.width = subdev_format.format.width;
 format.fmt.pix_mp.height = subdev_format.format.height;
 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUYV;
 printf("Size: %dx%d\n", format.fmt.pix_mp.width, format.fmt.pix_mp.height);
 ret = ioctl(fd, VIDIOC_S_FMT, &format);
 if (ret == -1)
  printf("VIDIOC_S_FMT failed\n");
 printf("Size: %dx%d\n", format.fmt.pix_mp.width, format.fmt.pix_mp.height);

 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 reqbufs.count = sizeof(mem) / sizeof(mem[0]);
 reqbufs.memory = V4L2_MEMORY_MMAP;
 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
 if (ret == -1)
  printf("VIDIOC_REQBUFS failed\n");

 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 buf.memory = V4L2_MEMORY_MMAP;
 buf.m.planes = &plane;
 buf.length = 1;
 for (i = 0; i < reqbufs.count; i++)
 {
  // allocate buffers to have somewhere to store the images
  buf.index = i;
  ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
  if (ret == -1)
  {
   printf("VIDIOC_QUERYBUF failed: i=%d\n", i);
   break;
  }

  // query the physical address of each allocated buffer in order to mmap() those
  printf("i=%d, buf.length=%d, buf.m.planes[0]=%d, buf.m.planes[0].m.mem_offset=%d\n", i, buf.length, buf.m.planes[0].length, buf.m.planes[0].m.mem_offset);
  mem[i] = mmap(NULL, buf.m.planes[0].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.planes[0].m.mem_offset);
  memsize[i] = buf.m.planes[0].length;
  if (mem[i] == MAP_FAILED)
   printf("map failed: i=%d\n", i);
  memset(mem[i], 0, memsize[i]);

  // Before the buffers can be filled with data, the buffers has to be enqueued.
  // Enqueued buffers will lock the memory pages used so that those cannot be swapped out during usage.
  // The buffers remain locked until that are dequeued.
  ret = ioctl(fd, VIDIOC_QBUF, &buf);
  if (ret == -1)
   printf("VIDIOC_QBUF failed: i=%d\n", i);
 }

 // start acquire video frames and use the queued buffers to store them
 ret = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 ret = ioctl(fd, VIDIOC_STREAMON, &ret);
 if (ret == -1)
  printf("VIDIOC_STREAMON failed\n");

 for (i = 0; i < 50; i++)
 {
  // Once buffers are filled with video data, those are ready to be dequeued and consumed by the application.
  // This ioctl will be blocking (unless O_NONBLOCK is used) until a buffer is available.
  // VIDIOC_DQBUF works similar to VIDIOC_QBUF but it populates the v4l2_buffer.index field with the index number
  // of the buffer that has been dequeued.
  buf.index = i % reqbufs.count;
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  ret = ioctl(fd, VIDIOC_DQBUF, &buf);
  if (ret == -1)
   printf("VIDIOC_DQBUF failed: i=%d, buf.index=%d\n", i, buf.index);
  else
  {
   printf("i=%d, buf.index=%d, buf.length=%d, buf.m.planes[0].length=%d\n", i, buf.index, buf.length, buf.m.planes[0].length);
   if (access("photos", 0) == -1)
    mkdir("photos", 0755);
   snprintf(filename, sizeof(filename), "photos/photo%d.bmp", i);
   convert_to_bitmap(mem[buf.index], buf.m.planes[0].length, filename, format.fmt.pix_mp.width, format.fmt.pix_mp.height);
  }

  // As soon the buffer is dequeued and processed, the application has to immediately queue back the buffer
  // so that the driver layer can fill it with new frames.
  // This is usually part of the application main-loop.
  ret = ioctl(fd, VIDIOC_QBUF, &buf);
  if (ret == -1)
   printf("VIDIOC_QBUF failed: buf.index=%d\n", buf.index);
 }

 // Once we are done with the video capturing, we can stop the streaming.
 // This will unlock all enqueued buffers and stop capture frames.
 ret = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 ret = ioctl(fd, VIDIOC_STREAMOFF, &ret);
 if (ret == -1)
  printf("VIDIOC_STREAMOFF failed\n");

 for (i = 0; i < reqbufs.count; i++)
 {
  if (mem[i] != NULL && mem[i] != MAP_FAILED)
   munmap(mem[i], memsize[i]);
 }

 close(fd);
 return ret;
}

 

 
一派掌門 二十級
9樓 發表于:2025-6-17 18:12

【test\ov5640\bmp.h】

#define MAX_PATH 260
#define BI_RGB 0
typedef int32_t LONG;
typedef uint16_t WORD;
typedef uint32_t DWORD;

#pragma pack(push, 1)
typedef struct
{
 WORD bfType;
 DWORD bfSize;
 WORD bfReserved1;
 WORD bfReserved2;
 DWORD bfOffBits;
} BITMAPFILEHEADER;

typedef struct
{
 DWORD biSize;
 LONG biWidth;
 LONG biHeight;
 WORD biPlanes;
 WORD biBitCount;
 DWORD biCompression;
 DWORD biSizeImage;
 LONG biXPelsPerMeter;
 LONG biYPelsPerMeter;
 DWORD biClrUsed;
 DWORD biClrImportant;
} BITMAPINFOHEADER;
#pragma pack(pop)

 

 
一派掌門 二十級
10樓 發表于:2025-6-17 18:12

【test\ov5640\Makefile】

CC=../../tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc

all: ov5640

 

 
一派掌門 二十級
11樓 發表于:2025-6-17 18:13

【串口输出】

luckfox login: root
Password:

Login incorrect
luckfox login: root
Password:
[root@luckfox root]#
[root@luckfox root]#
[root@luckfox root]# ls
ov5640  photos
[root@luckfox root]# rm -rf photos
[root@luckfox root]# ls
ov5640
[root@luckfox root]# ./ov5640
interval=1/15
code=0x2006, field=1
Driver: rkcif
Card: rkcif
Bus info: platform:rkcif-mipi-lvds
Version: 330400
VIDIOC_ENUM_FMT start
        1.Y/CbCr 4:2:2
        2.Y/CrCb 4:2:2
        3.Y/CbCr 4:2:0
        4.Y/CrCb 4:2:0
        5.YUYV 4:2:2
        6.YVYU 4:2:2
        7.UYVY 4:2:2
        8.VYUY 4:2:2
VIDIOC_ENUM_FMT end
Size: 2592x1944
Size: 2592x1944
i=0, buf.length=1, buf.m.planes[0]=10119168, buf.m.planes[0].m.mem_offset=0
i=1, buf.length=1, buf.m.planes[0]=10119168, buf.m.planes[0].m.mem_offset=101212
16
i=2, buf.length=1, buf.m.planes[0]=10119168, buf.m.planes[0].m.mem_offset=202424
32
i=3, buf.length=1, buf.m.planes[0]=10119168, buf.m.planes[0].m.mem_offset=303636
48
i=0, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=1, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=2, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=3, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=4, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=5, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=6, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=7, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=8, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=9, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=10, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=11, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=12, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=13, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=14, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=15, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=16, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=17, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=18, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=19, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=20, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=21, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=22, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=23, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=24, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=25, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=26, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=27, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=28, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=29, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=30, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=31, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=32, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=33, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=34, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=35, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=36, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=37, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=38, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=39, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=40, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=41, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=42, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=43, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=44, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=45, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
i=46, buf.index=2, buf.length=1, buf.m.planes[0].length=10119168
i=47, buf.index=3, buf.length=1, buf.m.planes[0].length=10119168
i=48, buf.index=0, buf.length=1, buf.m.planes[0].length=10119168
i=49, buf.index=1, buf.length=1, buf.m.planes[0].length=10119168
[root@luckfox root]#

 

 
一派掌門 二十級
12樓 發表于:2025-6-17 18:19
照片的采集速度很快,但是板载flash的读写速度很慢。
2592x1944分辨率下,每张bmp照片的大小是14.4MB,保存一张照片到flash上要好几秒。
板载flash空间有限,最多只能采集13张照片(photo0.bmp~photo12.bmp),而且摄像头刚启动时采集的四张照片(photo0~3)是不正确的,从photo4开始才是正确的照片。到最后flash空间满了,photo13.bmp不完整,所以在电脑上无法查看。
 
一派掌門 二十級
13樓 發表于:2025-6-17 18:32

【电路图】

注意13脚MCLK0必须外接24MHz有源晶振,不能用RV1106的I/O口输出的24MHz时钟,否则OV5640 I2C接口无响应。

 
一派掌門 二十級
14樓 發表于:2025-6-17 18:38
 

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:45 回複數:13
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2025-6-17 18:38
 
©2010-2025 Purasbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。