【FPGA】摄像头模块OV5640

本篇文章包含的内容

  • 一、OV5640简介
    • 1.1 基本概述
    • 1.2 工作时序
      • 1.2.1 DVP Timing(数据传输时序)
      • 1.2.2 帧曝光工作模式
    • 1.3 OV5640 闪光灯工作模式
      • 1.3.1 Xenon Flash(氙灯闪烁)模式
      • 1.3.2 LED 1&2 模式
      • 1.3.3 LED 3模式
      • 1.3.4 手动开启闪光灯
    • 1.4 模块硬件设计
  • 二、SCCB通信协议
    • 2.1 SCCB读写时序
    • 2.2 SCCB与I2C的区别
  • 三、代码设计
    • 3.1 设置输出像素大小
      • 3.1.1 设置 ISP input size(X/Y_ADDR)
      • 3.1.2 设置 pre-scaling size (OFFSET)
      • 3.1.3 设置 data output size(OUTPUT)
    • 3.2 读取摄像头输出像素数据


  • 开发板:正点原子的达芬奇开发板(或MicroPhase的Z7-Lite 7020开发板)
  • FPGA型号:XC7A35TFGG484-2(或XC7Z020CLG400-2)
  • Vivado版本:2020.2
  • 参考课程链接:正点原子手把手教你学FPGA-基于达芬奇开发板 A7
  • OV5640模块:正点原子ATK-OV5640

一、OV5640简介

1.1 基本概述

  OV5640是OV(OMNIVISION)公司设计的一款CMOS图像传感器,最高输出500万像素的图像,最高分辨篇格式为QSXVGA(2592×1944),数据接口采用DVP,控制接口为SCCB。可以输出RGB565/RGB555/RGB444、YUV(422/420)、YCbCr422和JPEG格式,可以对图像进行白平衡、饱和度、色度、锐度、Gamma曲线等调节。图像分辨率、帧率可调。
  OV5640支持LED补光、MIPI(移动产业处理器接口,常用于手机摄像头)输出接口和 DVP(数字视频并行,本次实验使用这个接口) 输出接口选择、ISP(图像信号处理)以及AFC(自动聚焦控制)等功能。
在这里插入图片描述
  控制OV5640的核心在于了解它的时序电路和数据输出之间的关系,在FPGA端需要注意以下标黄的端口,它们都是OV5640的控制输入引脚。下面对时序生成和系统逻辑控制电路的引脚作一些说明:

  • PWDN休眠控制
  • RESETB复位信号
  • FREX帧曝光控制
  • GPIO[3:0]:和自动聚焦和防震动相关配置有关(本次实验没有用到)
  • PCLK:像素同步时钟(由模块板载晶振提供)
  • HREF:行同步信号,可以理解为像素数据有效信号
  • VSYNC:场同步信号
  • STROBE:闪光灯控制(连接到模块板载LED)

  OV5640支持2592×1944(QSXVGA)及以下任意分辨率图像的输出。它是通过缩放和修改相关像素定位寄存器实现的。相关配置寄存器的配置地址及意义由下图给出。
在这里插入图片描述

  • X/Y_ADDR_ST/END:输出像素的开始位置和结束位置。
  • X/Y_OFFSET:缩放前输出场的偏移。
  • X/Y_OUTPUT_SIZE:输出像素大小。

1.2 工作时序

1.2.1 DVP Timing(数据传输时序)

在这里插入图片描述
在这里插入图片描述
  上图表示了OV5640在DVP模式下的数据输出时序,同时列出了以VGA(640×480)分辨率为例的不同区间的时间。

  • tp:在RGB565格式下,一个 t p tp tp等于两倍的 t P C L K t_{PCLK} tPCLK,因为一个像素的有效数据需要两个时钟周期传输。

1.2.2 帧曝光工作模式

在这里插入图片描述
  OV5640拥有三种曝光模式,在模式0下,帧曝光控制引脚FREQ作输入,曝光脉冲请求通过FPGA发出;在模式1下,曝光请求通过I2C(SCCB)总线发出,帧曝光控制引脚FREQ作输出,通知外部主机(FPGA)将要开始曝光,LED功能只有在模式0和模式1下才会工作;滚动曝光模式下曝光控制功能失效。
在这里插入图片描述

1.3 OV5640 闪光灯工作模式

在这里插入图片描述

  在了解闪光灯信号strobe信号之前,需要注意,闪光灯的所有工作模式只在帧曝光模式0和模式1下有效。滚动帧曝光下闪光灯不工作。

1.3.1 Xenon Flash(氙灯闪烁)模式

  "Xenon"是指氙灯(xenon flash)模式。氙灯是一种基于氙气放电的强光源,当电流通过充满氙气的灯管时,氙气被激发产生亮白色的光。在摄影和摄像中,氙灯闪光灯被广泛用于提供短时间内的高强度照明,以便在拍摄照片或视频时,尤其是在低光环境下,获得更好的曝光效果。在脉冲请求strobe request信号到来后,经历三帧时间,strobe pulse将输出一个极短的脉冲。该功能需要通过寄存器配置。上电后默认工作在该模式下。
在这里插入图片描述

1.3.2 LED 1&2 模式

  LED1和LED2模式均为LED闪烁模式,在LED曝光期间的帧数据会跳过输出。该功能需要寄存器配置。
在这里插入图片描述
在这里插入图片描述

1.3.3 LED 3模式

  在LED3模式下,LED灯会保持常亮。
在这里插入图片描述

1.3.4 手动开启闪光灯

  与LED工作模式无关,我们可以通过SCCB总线发送指令修改寄存器的值,手动开启或关闭闪光灯。通过依次配置寄存器0x30160x301C0x3019Bit[1]即可打开或关闭闪光灯。

在这里插入图片描述
在这里插入图片描述
asd

1.4 模块硬件设计

在这里插入图片描述

二、SCCB通信协议

  SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV(OMNIVISION)公司定义和发展的两线/三线式串行总线。该总线控制OV系列摄像头大部分的功能,包括图像数据格式、分辨篇以及图像处理参数等。两线SCCB只能实现“一主一从”的控制,而三线结构可以实现对多个从机进行控制。OV公司为了减少传感器引脚的封装,现在SCCB大多采用两线式接口总线。

  • SIO_C/SCL:只能由主机(FPGA)配置;
  • SIO_D/SDA:上面有一个三态门,可以实现双向数据传输,可以由主机控制,也可以由从机控制

  SCCB协议与I2C协议十分相似,甚至在有些驱动历程中直接将I2C的驱动程序拿来使用。了解I2C协议之前有必要熟悉I2C协议的相关使用,在这里不作过多赘述。

2.1 SCCB读写时序

  SCCB 总线跟 I2C 十分类似,起始信号、停止信号与 I2C 一样,SCCB 定义数据传输的基本单元为相(phase),每个相传输一个字节数据。SCCB 只包含三种传输周期:三相写周期、两相写周期和两相读周期。

  1. 三相写周期:依次为(开始信号)设备地址(写命令)、寄存器地址、数据(结束信号)。
    在这里插入图片描述

  2. 两相写周期:依次为(开始信号)设备地址(写命令)、寄存器地址(结束信号)。
    在这里插入图片描述

  3. 两相读周期:依次为(开始信号)设备地址(读命令)、数据(结束信号)。
    在这里插入图片描述

  在写入数据时,只执行三相写周期;在读出数据时,先执行两相写周期(虚写),再执行两相读周期。在SCCB协议中,每一相后有一个X信号,表示不需要关心这一位信号,与I2C协议不同,SCCB协议不用等待从器件响应(拉低)。两相读周期最后的NA信号表示不响应,即主机不会拉低信号线给从机发送响应。

2.2 SCCB与I2C的区别

  1. SCCB第九位为不关心位,而I2C传输协议中为应答位。
  2. SCCB每次传输不超过三相(Phase),即不能连续读写;I2C可以连续读写。
  3. SCCB读传输协议中没有重复开始的操作,在虚写完成之后,必须先发出一次停止信号,再重新发出开始信号;I2C协议中不需要在虚写之后添加停止,只需要再发送一次开始信号并执行后续操作即可。

三、代码设计

3.1 设置输出像素大小

在这里插入图片描述
  OV5640通过SCCB总线写入对应位置寄存器设置输出像素大小。实际上I2C的驱动程序完全可以兼容SCCB通信,所以重点在于OV5640初始化工作中对寄存器值的操作,在正点原子的历程中要配置250个寄存器,还是相当繁琐的。其中首先要注意的就是输出像素大小的定义。

3.1.1 设置 ISP input size(X/Y_ADDR)

	/* 部分设置代码…… */

	// 设置感光区域的“开窗大小”,开窗区域不是最终的显示区域
	8'd212:
        i2c_data <= {16'h3800,8'h00};
    8'd213:
        i2c_data <= {16'h3801,8'h00};	// 起始点x坐标 16'h0000
    8'd214:
        i2c_data <= {16'h3802,8'h00};
    8'd215:
        i2c_data <= {16'h3803,8'h04};	// 起始点x坐标 16'h0004
    8'd216:
        i2c_data <= {16'h3804,8'h0a};
    8'd217:
        i2c_data <= {16'h3805,8'h3f};	// 终止点x坐标 16'h0a3f = 16'd2623
    8'd218:
        i2c_data <= {16'h3806,8'h07};
    8'd219:
        i2c_data <= {16'h3807,8'h9b};	// 终止点y坐标 16'h079b = 16'd1947
	

3.1.2 设置 pre-scaling size (OFFSET)

	/* 部分设置代码…… */

	// 设定画幅OFFSET,在这里X_OFFSET = 0x0010 (16)
	8'd46 :
        i2c_data <= {16'h3810,8'h00}; 	// Timing Hoffset[11:8]
    8'd47 :
        i2c_data <= {16'h3811,8'h10}; 	// Timing Hoffset[7:0]
    8'd48 :
        i2c_data <= {16'h3812,8'h00}; 	// Timing Voffset[10:8]

	/* 部分设置代码…… */

	// OFFSET设置,Y_OFFSET = 0x0006(6)
	8'd228:
        i2c_data <= {16'h3813,8'h06};	 // Timing Voffset[7:0]

3.1.3 设置 data output size(OUTPUT)

  OV5640内部的ISP算法可以直接将压缩前获得的图像通过算法压缩成定义的像素大小,只需要在输入中给出像素大小即可。

	/* 部分设置代码…… */

	//设置输出像素个数(ISP压缩到800*480)
    //DVP 输出水平像素点数高4位
    8'd220:
        i2c_data <= {16'h3808,{4'd0,cmos_h_pixel[11:8]}};
    //DVP 输出水平像素点数低8位
    8'd221:
        i2c_data <= {16'h3809,cmos_h_pixel[7:0]};
    //DVP 输出垂直像素点数高3位
    8'd222:
        i2c_data <= {16'h380a,{5'd0,cmos_v_pixel[10:8]}};
    //DVP 输出垂直像素点数低8位
    8'd223:
        i2c_data <= {16'h380b,cmos_v_pixel[7:0]};


    //水平总像素大小高5位
    8'd224:
        i2c_data <= {16'h380c,{3'd0,total_h_pixel[12:8]}};
    //水平总像素大小低8位
    8'd225:
        i2c_data <= {16'h380d,total_h_pixel[7:0]};
    //垂直总像素大小高5位
    8'd226:
        i2c_data <= {16'h380e,{3'd0,total_v_pixel[12:8]}};
    //垂直总像素大小低8位
    8'd227:
        i2c_data <= {16'h380f,total_v_pixel[7:0]};
         

3.2 读取摄像头输出像素数据

  • cmos_capture_data.v
module cmos_capture_data(
        input rst_n,					// 复位信号

        input cam_pclk,					// coms 数据像素同步时钟
        input cam_vsync,				// coms 场同步信号
        input cam_href,					// cmos 行有效信号(数据输出有效)
        input [7:0] cam_data,

        output cmos_frame_vsync,
        output cmos_frame_href,
        output cmos_frame_valid,
        output [15:0] cmos_frame_data
    );

    // 寄存器全部配置完成后,先等待10帧的时间
	// 待寄存器配置生效后再开始采集图像
    parameter WAIT_FRAME = 4'd10;            // 寄存器等待稳定的帧个数

    // reg define
    reg cam_vsync_d0;
    reg cam_vsync_d1;
    reg cam_href_d0;
    reg cam_href_d1;
    reg [3:0] cmos_ps_cnt;          // 等待帧数稳定计数器
    reg [7:0] cam_data_d0;
    reg [15:0] cmos_data_t;         // 8位转16位临时寄存器
    reg byte_flag;            		// 16位RGB数据转换完成的标志信号
    reg byte_flag_d0;
    reg frame_val_flag;            	// 帧有效标志

    wire pos_vsync;            		// 采输入场同步信号的上升沿

    // 采输入场同步信号的上升沿
    assign pos_vsync = (~cam_vsync_d1) & cam_vsync_d0;

    // 输出帧有效信号和行有效信号
    assign cmos_frame_vsync = frame_val_flag ? cam_vsync_d1 : 1'b0;
    assign cmos_frame_href = frame_val_flag ? cam_href_d1 : 1'b0;

    // 输出数据使能有效信号
    assign cmos_frame_valid = frame_val_flag ? byte_flag_d0 : 1'b0;

    // 输出像素数据
    assign cmos_frame_data = frame_val_flag ? cmos_data_t : 1'b0;

	// 对摄像头的场同步信号和行同步信号进行打拍获取上升沿
	always @(posedge cam_pclk or negedge rst_n) begin
        if(!rst_n) begin
            cam_vsync_d0 <= 1'b0;
            cam_vsync_d1 <= 1'b0;
            cam_href_d0 <= 1'b0;
            cam_href_d1 <= 1'b0;
        end
        else begin
            cam_vsync_d0 <= cam_vsync;
            cam_vsync_d1 <= cam_vsync_d0;
            cam_href_d0 <= cam_href;
            cam_href_d1 <= cam_href_d0;
        end
    end

    // 对帧数进行计数
    always @(posedge cam_pclk or negedge rst_n) begin
        if(!rst_n)
            cmos_ps_cnt <= 4'd0;
        else if(pos_vsync && (cmos_ps_cnt < WAIT_FRAME))
            cmos_ps_cnt <= cmos_ps_cnt + 4'd1;
    end

    // 帧有效标志
    always @(posedge cam_pclk or negedge rst_n) begin
        if(!rst_n)
            frame_val_flag <= 1'b0;
        else if((cmos_ps_cnt == WAIT_FRAME) && pos_vsync)
            frame_val_flag <= 1'b1;
    end

    // 8位数据转16位RGB565数据
    always @(posedge cam_pclk or negedge rst_n) begin
        if(!rst_n) begin
            cmos_data_t <= 16'd0;
            cam_data_d0 <= 8'd0;
            byte_flag <= 1'b0;
        end
        else if(cam_href) begin			// 当数据有效信号
            byte_flag <= ~byte_flag;
            cam_data_d0 <= cam_data;	// 打拍暂存上一个pclk的字节数据
            if(byte_flag)
                cmos_data_t <= {cam_data_d0, cam_data};
        end
        else begin
            byte_flag <= 1'b0;
            cam_data_d0 <= 8'b0;
        end
    end

    // 打一拍产生输出数据有效信号 (cmos_frame_valid)
    always @(posedge cam_pclk or negedge rst_n) begin
        if(!rst_n)
            byte_flag_d0 <= 1'b0;
        else
            byte_flag_d0 <= byte_flag;
    end

endmodule


  持续不定期更新完善中……


  原创笔记,码字不易,欢迎点赞,收藏~ 如有谬误敬请在评论区不吝告知,感激不尽!博主将持续更新有关嵌入式开发、FPGA方面的学习笔记。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/469090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

milvus安装

milvus安装 sudo curl -L “https://github.com/docker/compose/releases/download/1.29.2/docker-compose- $ (uname -s)- $ (uname -m)” -o /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose sudo ln -s /usr/local/bin/docker-compose /usr/bin/…

Leetcode992-K个不同整数的子数组[两种方法] 关键词 滑窗

文章目录 题目方法一&#xff1a;滑窗右端每次1&#xff0c;左端来回滑动方法二&#xff1a;&#xff08;最多K种的子串数&#xff09; - &#xff08;最多K-1种的子串数&#xff09; 恰好K种 题目 1 < nums.length < 20000 1 < nums[i], k < nums.length 方法一…

Pytest 教程:从 0 到 1 搭建 Pytest 接口自动化测试项目

从 0 到 1 搭建 Pytest 接口自动化测试项目 1.创建项目目录 mkdir Pytest-API-Testing-Demo 2.项目初始化 // 进入项目文件夹下cd Pytest-API-Testing-Demo// 创建项目 python 项目虚拟环境python -m venv .env// 启用项目 python 项目虚拟环境source .env/bin/activate 3…

【InternLM 笔记】OpenXLAB浦源的基本操作

OpenXLab网址 网址&#xff1a;OpenXLab浦源 模型 创建模型 页面右上角选择【创建】然后选择【创建模型】 创建模型的页面如下 感觉页面中的提示信息填写相应的内容&#xff0c;全部填完后点页面下方的【立即创建】完成模型的创建 模型上传 安装所需的工具 apt install …

最全参赛指南!2024 年(第 17 届)中国大学生计算机设计大赛大数据主题赛现已开赛

2024 年&#xff08;第 17 届&#xff09;中国大学生计算机设计大赛大数据主题赛“数据解读乡村发展”赛题已于和鲸平台正式开赛&#xff0c;一个月来&#xff0c;全国已有超百所高校近千位优秀本科生积极响应大赛号召完成报名。 为进一步助力广大师生顺利参赛&#xff0c;和鲸…

RabbitMQ问题

如何实现顺序消费&#xff1f; 消息放入到同一个队列中消费 如何解决消息不丢失&#xff1f; 方案&#xff1a; 如上图&#xff1a;消息丢失有三种情况&#xff0c;解决了以上三种情况就解决了丢失的问题 1、丢失1--->消息在到达交换机的时候&#xff1b;解决&#xff1…

阿里云2核4G4M轻量应用服务器价格165元一年

阿里云优惠活动&#xff0c;2核4G4M轻量应用服务器价格165元一年&#xff0c;4Mbps带宽下载速度峰值可达512KB/秒&#xff0c;系统盘是60GB高效云盘&#xff0c;不限制月流量&#xff0c;2核2G3M带宽轻量服务器一年87元12个月&#xff0c;在阿里云CLUB中心查看 aliyun.club 当前…

鸿蒙Harmony应用开发—ArkTS声明式开发(绘制组件:Path)

路径绘制组件&#xff0c;根据绘制路径生成封闭的自定义形状。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Path(value?: { width?: number | string; height?: number |…

[已解决] vscode 跳转 python 代码失败

linux 环境下&#xff0c;"Ctrl 单击" 跳转函数定义失败&#xff0c;可以尝试下面的方法: setting -> 输入 go to definition -> 将下列两项配置改为 goto (不过当存在多个同名函数时&#xff0c;可能跳转会不符合预期)

ThingsBoard Edge 设备连接

文章目录 一、创建设备1.创建设备配置2.创建设备 二、上传遥测1.MQTTX 工具2.上传遥测 三、属性1.属性类型2.上传客户端属性3.下载共享属性4.订阅共享数据 四、设备告警1.配置告警规则2.清除报警规则3.测试3.1.设备告警3.1.清除告警 五、规则链1.规则管理2.Edge 查看规则链 Thi…

实现安卓连接阿里云物联网平台(2)

完整工程链接 链接&#xff1a;https://pan.baidu.com/s/1ykcJHPBSKBXVMaMWKoVRvA?pwd8888 提取码&#xff1a;8888 &#xff08;1&#xff09;创建一个新工程 &#xff08;2&#xff09;添加mqtt包的依赖 implementation org.eclipse.paho:org.eclipse.paho.client.mqttv…

AI将如何影响我们的生活?

1. AI 会如何影响你的生活 通用聊天场景&#xff1a;也即 ChatGPT 本身&#xff0c;或者用 gpt-3.5 的 api 实现的各类网站或小程序。他们没有明确的问题场景&#xff0c;但反而可以解决非常多的问题&#xff0c;比如搜索一些常见问题的答案、编个笑话等&#xff0c;可以当个搜…

力扣刷题(DAY09-DAY11)

Day09 0958. 二叉树的完全性检验 知识点&#xff1a;完全二叉树&#xff1a;在一棵完全二叉树中&#xff0c;除了最后一层外&#xff0c;所有层都被完全填满&#xff0c;并且最后一层中的所有节点都尽可能靠左。最后一层&#xff08;第 h 层&#xff09;中可以包含 1 到 个节点…

白酒:原料的加工方式对白酒品质的影响研究

在豪迈白酒的酿造过程中&#xff0c;原料的加工方式对白酒的品质起着至关重要的作用。云仓酒庄深知这一点&#xff0c;并进行了深入的研究和实践。本文将探讨原料的加工方式如何影响白酒的品质&#xff0c;以及酒庄如何通过改进加工方式来提升白酒的品质。 首先&#xff0c;原料…

web服务架构

1 Web服务器&#xff08;如Nginx、Apache等&#xff09;和Web应用框架&#xff08;如Flask、Django等&#xff09; Web服务器&#xff08;如Nginx、Apache等&#xff09;和Web应用框架&#xff08;如Flask、Django等&#xff09;在Web应用开发和部署中扮演着不同的角色&#xf…

Windows Server 各版本搭建远程访问 / VPN 服务器实现 VPN 连接(03~19)

一、Windows Server 2003 开机后点击添加或删除角色 点击下一步 勾选自定义&#xff0c;点击下一步 点击 远程访问/VPN 服务器&#xff0c;点击下一步 点击下一步 点击下一步 勾选自定义&#xff0c;点击下一步 选择配置类型&#xff0c;点击下一步 点击完成 点击是 点击完成…

RTSP视频监控EasyNVR安防视频云平台直播鉴权功能简述

RTSP协议视频监控系统EasyNVR安防视频云平台&#xff0c;可支持设备通过RTSP/Onvif协议接入并进行视频流的处理及分发&#xff0c;在视频监控场景中可实现视频实时监控直播、云端录像、云存储、录像检索与回看、告警、级联等&#xff0c;平台能将拉取过来的音视频流转化成适合全…

酷得智能电子方案 儿童对讲机

儿童对讲机的设计通常会考虑到孩子的使用习惯和安全&#xff0c;操作简单&#xff0c;适合不同年龄段的儿童使用。同时&#xff0c;为了防止孩子误操作&#xff0c;一些对讲机会有一键锁闭功能&#xff0c;确保除了对讲键之外的所有功能都不会被小朋友乱按。而且&#xff0c;儿…

解锁编程潜能:ChatGPT如何革新软件开发

目录 一、背景 二、功能描述 三、总结 一、背景 在这个飞速发展的数字时代&#xff0c;软件开发的效率和质量成了衡量一个开发者能力的重要标准。随着人工智能技术的不断进步&#xff0c;越来越多的开发者开始寻找能够提升工作效率的新方法。我就是其中之一&#xff0c;最近…