FPGA2-采集OV5640乒乓缓存后经USB3.0发送到上位机显示

news/2024/5/17 3:42:21/文章来源:https://blog.csdn.net/weixin_40615338/article/details/131992625

1.场景

基于特权A7系列开发板,采用OV5640摄像头实时采集图像数据,并将其经过USB3.0传输到上位机显示。这是验证数据流能力的很好的项目。其中,用到的软件版本,如下表所示,基本的硬件情况如下。该项目对应FPGA工程源码,qt工程源码,以及USB固件的下载地址

软件版本
QT5.15.0
Vivado2020.2
FX3 SDK1.3.4

器件

型号

厂商

FPGA

XLNX-XC7A35T-FTG256

赛灵思

DDR3

MICT-MT41K128M16JT-96

镁光

USB控制芯片

CYUSB3014-BZXI

赛普拉斯

摄像头

OV5640

豪威科技

 2.架构

如图,所示为该小项目的基本架构。其硬件部分由摄像头采集模组、DDR3存储芯片、FPGA芯片、USB控制芯片组成。软件部分包括FPGA数据采集处理代码、CYUSB3014应用固件、QT上位机软件三个部分组成。其中,FPGA数据采集处理代码主要包含了摄像头配置模块(含图示SCCB驱动)、摄像头数据捕获模块、DDR3读写控制模块、图像数据编码模块、USB读写控制模块;CYUSB应用固件包括下行USB控制传输模式实现、上行块传输模式实现两个部分;QT上位机包括USB通信模块和图像数据解码模块,RGB565图像数据显示模块。

项目实现了将采集得到的图像数据,经过USB传输线,传输至上位机进行画面实时显示的功能。具体为:①FPGA摄像头配置模块通过SCCB接口驱动协议完成摄像头的寄存器配置,使之DVP接口产生正确信号;②FPGA摄像头数据捕获模块通过DVP接口采集实时图像数据;③FPGA DDR3读写控制模块将采集到底数据先存入DDR3缓冲,并将数据从DDR3读出至数据编码模块;④FPGA数据编码模块对图像数据进行编码,做加入帧头的操作(暂时没做);⑤FPGA USB读写控制模块产生USB控制芯片的读写信号,将图像数据发送到USB控制芯片;⑥CYUSB3014应用固件通过块传输的传输模式,将图像数据发送至上位机;⑦上位机USB通信模块用于读取USB的传输数据;⑧上位机图像解码模块用于将读取到的编码过的图像数据进行解码;⑨上位机RGB565图像显示模块将解码得到的像素数据进行显示。最终完成了将摄像头采集到的图像数据进行实时显示的功能。

3.FPGA技术点

3.1SCCB协议

与IIC总线非常接近,可参考FPGA IIC接口通信

SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV(OmniVision的简称)公司定义和发展的三线式串行总线,该总线控制着摄像头大部分的功能,包括图像数据格式、分辨率以及图像处理参数等。该协议是兼容IIC协议的。为了节约管脚,OV公司采用的都是两线是类似于IIC的时钟线SIO_C和数据线SIO_D。                                                                                     

SSCB协议描述:

  1. Start传输开始标志:在时钟线SIO_C为高电平期间,SIO_D完成从高到低的跳变,代表着传输开始。
  2. Stop传输结束标志:在时钟线SIO_C为高电平期间,SIO_D由低到高完成跳变,代表着传输结束。
  3. 传输时序写:传输开始+ID Addr+R编号+数据DATA+传输结束

        ID ADDRESS是由7位器件地址和1位读写控制位构成(0:写 1:读);上图中的第9位X表示Don’t Care(不必关心位),该位是由从机(此处指摄像头)发出应答信号来响应主机表示当前ID Address、Sub-address和Write Data是否传输完成,但是从机有可能不发出应答信号,因此主机(此处指FPGA)可不用判断此处是否有应答,直接默认当前传输完成即可.Sub-address为8位寄存器地址,在摄像头的数据手册中定义了0x00~0xAC共173个寄存器(大概数),有些寄存器是可改写的,有些是只读的,只有可改写的寄存器才能正确写入。WriteData为8位写数据,每一个寄存器地址对应8位的配置数据

        4.传输时序读:传输开始+相1(ID ADDR)+相2(寄存器编号)+结束传输

  • 第一部分是写器件地址和寄存器地址,即先进行一次虚写操作,通过这种虚写操作使地址指针指向虚写操作中寄存器地址的位置,当然虚写操作也可以通过前面介绍的写传输协议来完成。其中ID Address代表的是期间地址,bit0为0(写)。Sub—address代表是寄存器地址。
  • 第二部分是读器件地址(ID Address bit0为1代表读)和读数据(Read Data),此时读取到的数据才是寄存器地址对应的数据。上图中的NA位由主机(这里指FPGA)产生,由于SCCB总线不支持连续读写,因此NA位必须为高电平。

3.2OV5640模组

与多数主流CMOS图像传感器一样,OV5640通过寄存器配置工作参数,方式就是SCCB协议,寄存器的内容很多,下面讲几个关键的,其余可查阅手册了解使用。

1.图像窗口设置

 

ISP 输入窗口设置(ISP Input Size)允许用户设置整个传感器显示区域(physical pixel size,2632*1951,其中 2592*1944 像素是有效的),开窗范围从 0*0~2632*1951 都可以任意设置。也就是上图中的 X_ADDR_ST(寄存器地址 0x3800、0x3801)、Y_ADDR_ST(寄存器地址 0x3802、0x3803)、X_ADDR_END(寄存器地址 0x3804、0x3805)和 Y_ADDR_END(寄存器地址 0x3806、0x3807)寄存器。该窗口设置范围中的像素数据将进入 ISP 进行图像处理。

ISP(Image Signal Processor),即图像处理,主要作用是对前端图像传感器输出的信号做后期处理,主要功能有线性纠正、噪声去除、坏点去除、内插、白平衡、自动曝光控制等,依赖于ISP才能在不同的光学条件下都能较好的还原现场细节,ISP技术在很大程度上决定了摄像机的成像质量。

预缩放窗口设置(pre-scaling size)允许用户在 ISP 输入窗口的基础上进行裁剪,用于设置将进行缩放的窗口大小,该设置仅在 ISP 输入窗口内进行 X/Y 方向的偏移。可以通过 X_OFFSET(寄存器地址 0x3810、0x3811)和 Y_OFFSET(寄存器地址 0x3812、0x3813)进行配置。

输出大小窗口设置(data output size)是在预缩放窗口的基础上,经过内部 DSP 进行缩放处理,并将处理后的数据输出给外部的图像窗口,图像窗口控制着最终的图像输出尺寸。可以通过 X_OUTPUT_SIZE(寄存器地址 0x3808、0x3809)和 Y_OUTPUT_SIZE(寄存器地址 0x380A、0x380B)进行配置。注意:当输出大小窗口与预缩放窗口比例不一致时,图像将进行缩放处理(图像变形),仅当两者比例一致时,输出比例才是 1:1(正常图像)。

右侧 data output size 区域,才是 OV5640 输出给外部的图像尺寸,也就是显示在显示器或者液晶屏上面的图像大小。输出大小窗口与预缩放窗口比例不一致时,会进行缩放处理,在显示器上面看到的图像将会变形。

实际配置的图像分辨率中,将3808=0x02 3809=0x80,0x0280=10’640;   380a=01 380b=e0,0x01e0=480。

2.输出图像格式设置

OV5640 支持多种不同的数据像素格式,包括 YUV(亮度参量和色度参量分开表示的像素格式)、RGB(其中 RGB 格式包含 RGB565、RGB555 等)以及 RAW(原始图像数据),通过寄存器地址 0x4300 配置成不同的数据像素格式。将寄存器 0x4300 寄存器的 Bit[7:4]设置成 0x6 ,将寄存器 0x4300 寄存器的 Bit[3:0]设置成0x1即可将输出像素格式设置为RGB565。

3.3DVP接口

DVP接口就是digital video port的简称,即数字视频端口。常见的视频采集接口有LVDS、MIPI,DVP是速度较慢的并行传输的接口,在高速的传感器上已经很少能见到该接口了,下面简单介绍一下DVP,下图为VGA帧的DVP接口时序图和接口管脚图。

 

说明1:不同的分辨率,上图中的每一个上升沿和每一个下降沿的时间是固定的,时间的单位是tp(指的是输出一个时钟像素数据所需要的时间),当配置摄像头的输出格式为8位raw时,tp=tPCLK,当为YUV\RGB的时候,tp=2*tPCLK。因此输出一帧图像所需要的时间与tPCLK是息息相关的。而决定像素时钟PCLK的是XCLK(控制芯片输出给驱动sensor的时钟)与寄存器的配置。因此,决定摄像头输出的帧频大小取决于XCLK与相关时钟倍频寄存器的配置。

说明2:时序关系,当场同步信号的有效信号到来时,开始一帧数据的传输,当行同步的有效信号到来时,开始一行数据的传输,每行数据之间有传输间隔,帧与帧之间除了包含480个行同步有效信号外还有其他的数据无效时间。

VSYNC:场同步信号,由摄像头输出,用于标志一帧数据的开始与结束。上图中VSYNC的高电平作为一帧的同步信号,在低电平时输出的数据有效。需要注意的是场同步信号是可以通过设置某寄存器进行取反的,即低电平同步高电平有效。

HREF/HSYNC:行同步信号,由摄像头输出,用于标志一行数据的开始与结束。上图中的HREF和HSYNC是由同一引脚输出的,只是数据的同步方式不一样。本次实验使用的是HREF格式输出,当HREF为高电平时,图像输出有效,可以通过寄存器进行配置。

D[9:0]:数据信号,由摄像头输出,在RGB格式输出中,只有高8位D[9:2]是有效的;

XCLK:控制芯片输出给驱动sensor的时钟。

PCLK:像素时钟,每一个时钟输出一个或者半个像素数据。

SCL、SDA :IIC(SCCB)用来配置sensor寄存器的接口。

3.4DDR3读写接口

参考DDR3应用总结

DDR3读写接口使用的赛灵思的MIG IP核。为了匹配DDR3的读写速度,使用两个FIFO用于写入DDR3和读出DDR3。由于该平台设计中,读出DDR3的速度大约是USB3.0的传输速度(实测平均速度在370MB/s),远远大于摄像头的数据输出速度(不超过50MB\s)。故使用乒乓操作切换两块缓冲区,每一块缓冲区大小为一帧图像的大小;对于写操作,写完第一块缓冲区bank1之后,就切换到第二块缓冲区bank2继续写;由于读取速度大于写入速度,因此当读完bank1之后,去当前没有写操作的bank中读取数据;可能产生同一帧图片读取多次的情况,但保证了用户在上位机正常观看画面。

3.5 USB3.0接口

    参考USB3.0赛普拉斯方案

上行数据流使用块传输模式传输实时像素数据,实际测试。平均速度可达370MB\s。

4.QT技术点

多线程 参考QThread线程创建与使用

QT工程代码粘贴如下:

主线程图像显示代码Raw_Usb,app:

#include "raw_usb.h"
#include "ui_raw_usb.h"
#include <mythread.h>
#include <QThread>
#include <QDebug>
#include <QImage>
#include <QPixmap>Raw_Usb::Raw_Usb(QWidget *parent): QWidget(parent), ui(new Ui::Raw_Usb)
{ui->setupUi(this);ui->label_Show->resize(640,480);connect(ui->startBtn,&QPushButton::clicked,this,&Raw_Usb::SlotStart);connect(ui->stopBtn,&QPushButton::clicked,this,&Raw_Usb::SlotStop);//链接线程中的数据来更新界面的图像显示connect(thr,&MyThread::refreshUi,this,&Raw_Usb::responseUi,Qt::BlockingQueuedConnection);
}Raw_Usb::~Raw_Usb()
{delete ui;
}
void Raw_Usb::SlotStart()
{thr->start();ui->startBtn->setEnabled(false);ui->stopBtn->setEnabled(true);
}
void  Raw_Usb::SlotStop()
{if(thr->isRunning()){thr->stop();ui->startBtn->setEnabled(true);ui->stopBtn->setEnabled(false);}
}
//成熟槽函数,接收内存区指针来显示图片
void Raw_Usb::responseUi(uchar * addrBuf)
{ QPixmap pix;QImage img=QImage(addrBuf,640,480,QImage::Format_RGB16);pix=pix.fromImage(img);ui->label_Show->setPixmap(pix);
}

子线程数据接收代码mythread.app

#include "mythread.h"
#include <QDebug>
#include <CyAPI.h>
#include <raw_usb.h>
#include <QFile>
#include <QImage>
#include <QPixmap>
#include <QByteArray>
#include <QTimer>
MyThread::MyThread(QObject *parent) :QThread(parent)
{stopped = false;
}void MyThread::run()
{/*创建设备对象,通过发送带参信号Cam_Data_Usb显示USB设备相关信息*/CCyUSBDevice *Cam_Data_Usb=new CCyUSBDevice;    //创建一个设备对象/*******************USB设备相关准备工作**************************/uchar *recieve_Buffer=new uchar[640*480*2];     //定义接收缓存,FPGA--上位机,输入inLONG recieveLen =640*480*2;                     //定义函数参数字节长度bool flag_Recieve;                              //定义bool型标志UCHAR buik_Recieve = 0x81;                      //定义bulk传输发送接收端点for (int i=0;i< Cam_Data_Usb->DeviceCount(); i++) {Cam_Data_Usb->Open(i);                      //准备工作就绪,开启第i号设备} CCyUSBEndPoint *recieve_Endpt=Cam_Data_Usb->EndPointOf(buik_Recieve);//指定端点,使能传输while(!stopped) {flag_Recieve=recieve_Endpt->XferData(recieve_Buffer, recieveLen);//使能接收if(flag_Recieve){emit; refreshUi(recieve_Buffer);}}delete Cam_Data_Usb;delete []recieve_Buffer;//使用完之后释放内存空间stopped = false;
}void MyThread::stop()
{stopped=true;
}MyThread::~MyThread()
{
}

 

 5.效果

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

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

相关文章

VMware虚拟机中配置静态IP

目录 环境原因基础概念VMnet网络IPV4网络私有地址范围Vmnet8的作用网路通信的过程解决方法1&#xff1a;修改k8s组件重新启动解决方法2&#xff1a;配置静态IP系统网卡设置设置虚拟机网关修改虚拟机网卡 环境 本机系统&#xff1a;windows11虚拟机系统&#xff1a;CentOS-7-x8…

iOS - Apple开发者账户添加新测试设备

获取UUID 首先将设备连接XCode&#xff0c;打开Window -> Devices and Simulators&#xff0c;通过下方位置查看 之后登录(苹果开发者网站)[https://developer.apple.com/account/] &#xff0c;点击设备 点击加号添加新设备 填写信息之后点击Continue&#xff0c;并一路继续…

【EI/SCOPUS会议征稿】第四届机器学习与计算机应用国际学术会议(ICMLCA 2023)

ICMLCA 2023 第四届机器学习与计算机应用国际学术会议 2023 4th International Conference on Machine Learning and Computer Application 第四届机器学习与计算机应用国际学术会议(ICMLCA 2023)定于2023年10月27-29日在中国杭州隆重举行。本届会议将主要关注机器学习和计算…

iOS开发-CAShapeLayer与UIBezierPath实现微信首页的下拉菜单效果

iOS开发-CAShapeLayer与UIBezierPath实现微信首页的下拉菜单效果 之前开发中遇到需要使用实现微信首页的下拉菜单效果。用到了CAShapeLayer与UIBezierPath绘制菜单外框。 一、效果图 二、CAShapeLayer与UIBezierPath 2.1、CAShapeLayer是什么&#xff1f; CAShapeLayer继承自…

《Elasticsearch 源码解析与优化实战》第5章:选主流程

《Elasticsearch 源码解析与优化实战》第5章&#xff1a;选主流程 - 墨天轮 一、简介 Discovery 模块负责发现集群中的节点&#xff0c;以及选择主节点。ES 支持多种不同 Discovery 类型选择&#xff0c;内置的实现称为Zen Discovery ,其他的包括公有云平台亚马逊的EC2、谷歌…

shell中按照特定字符分割字符串,并且在切分后的每段内容后加上特定字符(串),然后再用特定字符拼接起来

文件中的内容&#xff0c;可以这么写&#xff1a; awk -F, -v OFS, {for(i1;i<‌NF;i){$i$i"_suffix"}}1 input.txt-F,&#xff1a;设置输入字段分隔符为逗号&#xff08;,&#xff09;&#xff0c;这将使awk按照逗号分割输入文本。-v OFS‘,’&#xff1a;设置输…

Banana Pi BPI-CM4 评测(计算模块 4),更快性能,旨在替换树莓派CM4

如果您正在寻找可靠的单板计算机来提升您的下一个项目&#xff0c;但无法找到满足您需求的 Raspberry Pi&#xff0c;请看看我是否可以提供帮助。在这篇详细的评论中&#xff0c;我将向您介绍 Banana Pi CM4&#xff0c;这是一款适用于各种任务的多功能且强大的解决方案。从经验…

GitLab开启双端认证并登录GitLab

GitLab开启双端认证并登录GitLab 1.介绍双端认证 单重认证——密码验证&#xff0c;这极其容易出现密码被盗&#xff0c;密码泄露等危险事件。 于是为了提高安全性&#xff0c;就出现了双因素认证&#xff0c;多因素认证。登录的时候不仅要输入账号和密码还需要输入一个验证码…

使用mediapipe训练手指数字识别

mediapipe手指数字识别 本文是从0开始创建一个识别手势的机器学习模型&#xff0c;为了识别手势&#xff0c;采用mediapipe模型&#xff0c;这个模型会返回手指的位置&#xff0c;之后再通过训练一个模型将这些位置分类得到手势 一、导入依赖 import cv2 import numpy as np…

MD-MTSP:成长优化算法GO求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、成长优化算法GO 成长优化算法&#xff08;Growth Optimizer&#xff0c;GO&#xff09;由Qingke Zhang等人于2023年提出&#xff0c;该算法的设计灵感来源于个人在成长过程中的学习和反思机制。学习是个人通过从外部世界获取知识而成长的过程&#xff0c;反思是检查个体自…

excel绘制折线图或者散点图

一、背景 假如现在通过代码处理了一批数据&#xff0c;想看数据的波动情况&#xff0c;是不是还需要写个pyhon代码&#xff0c;读取文件&#xff0c;绘制曲线&#xff0c;看起来也简单&#xff0c;但是还有更简单的方法&#xff0c;就是直接生成csv文件&#xff0c;csv文件就是…

【MyBatis】MyBatis 3.5+版本报错合集(持续更新)

报错&#xff1a;BindingException 1. org.apache.ibatis.binding.BindingException: Type interface xxx is not known to the MapperRegistry. 2. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xxx 解决方案 在pom.xml中添加如下代码…

python json保留汉字原始形式,而不是Unicode编码(Unicode码)(加ensure_ascii=False参数)

文章目录 问题解决办法测试 问题 如图&#xff0c;保存汉字的时候变成unicode码了。。。 代码是这样的&#xff1a; 解决办法 在Python中&#xff0c;可以使用json模块的ensure_ascii参数来控制是否将汉字转换为类似\u5730\u9707的Unicode编码。默认情况下&#xff0c;ensure…

SpringBoot整合第三方 Druid、MybatisPlus、Mybatis

整合第三方技术 整合JUnit Respostory 注解&#xff1a;数据类 1、导入测试对应的starter 2、测试类使用 SpringBootTest 修饰 3、使用自动装配的形式添加要测试的对象 classes的属性 其实主要找的是SpringBootApplication中的SpringBootConfiguration这个注解。也就是配置…

【Qt】QML-02:QQuickView用法

1、先看demo QtCreator自动生成的工程是使用QQmlApplicationEngine来加载qml文件&#xff0c;下面的demo将使用QQuickView来加载qml文件 #include <QGuiApplication> #include <QtQuick/QQuickView>int main(int argc, char *argv[]) {QGuiApplication app(argc,…

螺旋矩阵 II

给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 示例 2&#xff1a; 输入&#xff1a;n 1 输出&a…

JGJ59-2011建筑施工安全检查标准

为科学评价建筑施工现场安全生产&#xff0c;预防生产安全事故的发生&#xff0c;保障施工人员的安全和健康&#xff0c;提高施工管理水平&#xff0c;实现安全检查工作的标准化&#xff0c;制定本标准。 本标准适用于房屋建筑工程施工现场安全生产的检查评定。 建筑施工安全…

7.28 作业 QT

手动完成服务器的实现&#xff0c;并具体程序要注释清楚: widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QTcpSocket> //客户端类 #include <QMessageBox> //对话框类 #include …

更安全,更省心丨DolphinDB 数据库权限管理系统使用指南

在数据库产品使用过程中&#xff0c;为保证数据不被窃取、不遭破坏&#xff0c;我们需要通过用户权限来限制用户对数据库、数据表、视图等功能的操作范围&#xff0c;以保证数据库安全性。为此&#xff0c;DolphinDB 提供了具备以下主要功能的权限管理系统&#xff1a; 提供用户…

附录1-将uni-app运行到微信开发者工具

目录 1 在manifest.json写入AppID 2 配置微信开发者工具的安装路径 3 微信开发者工具的安全设置 4 运行 5 修改一些配置项 1 在manifest.json写入AppID 2 配置微信开发者工具的安装路径 如果你忘了安装在哪里了&#xff0c;可以右键快捷方式看一下属性 在运行设置…