FPGA2-采集OV5640乒乓缓存后经USB3.0发送到上位机显示
1.场景
基于特权A7系列开发板,采用OV5640摄像头实时采集图像数据,并将其经过USB3.0传输到上位机显示。这是验证数据流能力的很好的项目。其中,用到的软件版本,如下表所示,基本的硬件情况如下。该项目对应FPGA工程源码,qt工程源码,以及USB固件的下载地址
软件 | 版本 |
QT | 5.15.0 |
Vivado | 2020.2 |
FX3 SDK | 1.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协议描述:
- Start传输开始标志:在时钟线SIO_C为高电平期间,SIO_D完成从高到低的跳变,代表着传输开始。
- Stop传输结束标志:在时钟线SIO_C为高电平期间,SIO_D由低到高完成跳变,代表着传输结束。
- 传输时序写:传输开始+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.效果
相关文章:

FPGA2-采集OV5640乒乓缓存后经USB3.0发送到上位机显示
1.场景 基于特权A7系列开发板,采用OV5640摄像头实时采集图像数据,并将其经过USB3.0传输到上位机显示。这是验证数据流能力的很好的项目。其中,用到的软件版本,如下表所示,基本的硬件情况如下。该项目对应FPGA工程源码…...

亚信科技AntDB数据库专家参加向量数据库首次技术标准研讨会
2023年7月19日下午,中国通信标准化协会大数据技术标准推进委员会数据库与存储工作组(CCSA TC601 WG4)联合中国信通院数据库应用创新实验室(CAICT DBL)在线上召开《向量数据库技术要求》标准首次研讨会。本次会议由中国…...

Windows中实现右键把电子书通过邮件发到kindle
不使用第三方软件,通过Windows自带的函数,可以实现右键将电子书通过电子邮件发送到kindle邮箱,从而实现kindle电子书传送功能。实现过程如下: 1. 使用bat添加右键功能 打开资源管理器,在地址中输入%APPDATA%\Microso…...

Three.js之创建3D场景
参考资料 【G】Three.js官方文档:https://threejs.org/docs/ Three.js是一个流行的WebGL库,官方文档提供了详细的API参考和示例,适合学习和参考。【G】Three.js GitHub链接:https://github.com/mrdoob/three.js 这是一个流行的基…...

一个3年Android的找工作记录
作者:Petterp 这是我最近 1个月 的找工作记录,希望这些经历对你会有所帮助。 有时机会就像一阵风,如果没有握住,那下一阵风什么时候吹来,往往是个运气问题。 写在开始 先说背景: 自考本,3年经验࿰…...

CAS原理解析
CAS是一种乐观锁机制,一种比较并交换的过程和理念,用来解决线程安全问题,具体来讲就是对共享变量值的安全更新机制。能够保证原子、可见、一致性。这种交换过程是在Unsafe类中实现。 从一段简单的代码开始来对源码做分析 public static void…...

SQL项目实战:银行客户分析
大家好,本文将与大家分享一个SQL项目,即根据从数据集收集到的信息分析银行客户流失的可能性。这些洞察来自个人信息,如年龄、性别、收入和人口统计信息、银行卡类型、产品、客户信用评分以及客户在银行的服务时间长短等。对于银行而言&#x…...

【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—实战篇)
探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—下篇) Cluster XX的集群指令(扩展)写入记录主节点和备节点切换-CLUSTER FAILOVER新加入master节点新加入slave节点为slave节点重新分配master分配哈希槽删除…...

ubuntu
安装 sudo apt-get update sudo apt-get install mysql-server mysql-client 设置root密码 cat /etc/mysql/debian.cnf 查看默认密码 mysql -u debian-sys-maint -p 连接输入密码 use mysql; select user,plugin from user; update user set pluginmysql_native_passwor…...

【芯片设计- RTL 数字逻辑设计入门 3- Verdi 常用使用命令】
文章目录 Verdi 全局显示Verdi 前导 0 的显示Verdi 数据笔数统计Verdi 波形数据dump Verdi 全局显示 bsubi -n 16 -J sam visualizer -tracedir ./veloce.wave/debug_waveform.stw 打开波形后,如果想要看到所有信号的数据,可以点击下图中红框中的按钮&a…...

python-pytorch基础之cifar10数据集使用图片分类
这里写目录标题 总体思路获取数据集下载cifar10数据解压包文件介绍加载图片数字化信息查看数据信息数据读取自定义dataset使用loader加载建模训练测试建测试数据的loader测试准确性测试一张图片读取一张图片加载模型预测图片类型创建一个预测函数随便来张马的图片结果其他打开一…...

华纳云:linux下磁盘管理与挂载硬盘方法是什么
在Linux下进行磁盘管理和挂载硬盘的方法如下: 磁盘管理: a. 查看已连接的磁盘:可以使用命令 fdisk -l 或 lsblk 查看系统中已连接的磁盘信息,包括硬盘和分区。 b. 创建分区:如果磁盘是全新的,需要使用 f…...

ChatGPT + Stable Diffusion + 百度AI + MoviePy 实现文字生成视频,小说转视频,自媒体神器!(一)
ChatGPT Stable Diffusion 百度AI MoviePy 实现文字生成视频,小说转视频,自媒体神器!(一) 前言 最近大模型频出,但是对于我们普通人来说,如何使用这些AI工具来辅助我们的工作呢,或者参与进入我们的生活…...

linux strcpy/strncpy/sprintf内存溢出问题
本文主要介绍strcpy/strncpy/sprintf都是不安全的,可能存在内存溢出的问题。下来进行实例分析。 strcpy代码: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h>void test_func(char *str) {b…...

Jmeter如何添加插件
一、前言 在我们的工作中,我们可以利用一些插件来帮助我们更好的进行性能测试。今天我们来介绍下Jmeter怎么添加插件? 2023最新Jmeter接口测试从入门到精通(全套项目实战教程) 二、插件管理器 首先我们需要下载插件管理器j…...

flask---CBV使用和源码分析
1 cbv写法 -1 写个类,继承MethodView-2 在类中写跟请求方式同名的方法-3 注册路由:app.add_url_rule(/home, view_funcHome.as_view(home))#home是endpoint,就是路由别名#例子 class add(MethodView):def get(self):return holleapp.add_url…...

Qt 实现压缩文件、文件夹和解压缩操作zip
一、实现方式 通过Qt自带的库来实现,使用多线程方式,通过信号和槽来触发压缩与解压缩,并将压缩和解压缩结果回传过来。 使用的类: #include "QtGui/private/qzipreader_p.h" #include "QtGui/private/qzipwriter…...

简单工厂模式VS策略模式
简单工厂模式VS策略模式 今天复习设计模式,由于简单工厂模式和策略模式太像了,重新整理梳理一下 简单工厂模式MUL图: 策略模式UML图: 1、简单工厂模式中只管创建实例,具体怎么使用工厂实例由调用方决定,…...

【MySQL】触发器 (十二)
🚗MySQL学习第十二站~ 🚩本文已收录至专栏:MySQL通关路 ❤️文末附全文思维导图,感谢各位点赞收藏支持~ 一.引入 触发器是与表有关的数据库对象,作用在insert/update/delete语句执行之前(BEFORE)或之后(AFTER),自动触发并执行触发器中定义的SQL语句集合。它可以协助应…...

听说 Spring Bean 的创建还有一条捷径?
文章目录 1. resolveBeforeInstantiation1.1 applyBeanPostProcessorsBeforeInstantiation1.2 applyBeanPostProcessorsAfterInitialization1.3 案例 2. 源码实践2.1 切面 Bean2.2 普通 Bean 在 Spring Bean 的创建方法中,有如下一段代码: AbstractAutow…...

大数据课程E6——Flume的Processor
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Processor的概念和配置参数; ⚪ 掌握Processor的使用方法; ⚪ 掌握Processor的Default Processo; ⚪ 掌握Processor的Load Balance Processo; 一、Failover Sink Processor 1. …...

实现邮箱管理之gmail邮箱、office365(Azure)邮箱之披荆斩棘问题一览
要进行Office365邮箱的授权对接,你需要先申请一个应用,并获取授权访问令牌。 以下是一个简单的步骤: 登录 Azure 门户:https://portal.azure.com/创建一个新的应用程序,或者使用现有的应用程序。要创建新的应用程序&…...

(AcWing)多重背包问题 I,II
有 N 种物品和一个容量是 V 的背包。 第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数 N,…...

如何把几个视频合并在一起?视频合并方法分享
当我们需要制作一个比较长的视频时,将多个视频进行合并可以使得整个过程更加高效。此外,合并视频还可以避免出现“剪辑断层”的情况,使得视频内容更加连贯,更加容易被观众理解和接受。再有,合并视频还可以减少视频文件…...

【MyBatis】初学MyBatis
目录 MyBatis 是什么?MyBatis框架搭建1.添加MyBatis框架2.设置MyBatis配置数据库的相关链接信息xml 保存路径和命名格式 根据MyBatis写法完成数据库的操作MyBatis插件MyBatis传递参数查询${} 和 #{} 有什么区别?SQL注入问题 MyBatis like查询MyBatis多表…...

深度学习训练营之DCGAN网络学习
深度学习训练营之DCGAN网络学习 原文链接环境介绍DCGAN简单介绍生成器(Generator)判别器(Discriminator)对抗训练 前置工作导入第三方库导入数据数据查看 定义模型初始化权重定义生成器generator定义判别器 模型训练定义参数模型训…...

自定义MVC增删改查
目录 mymvcdemo是自定义mvc框架的使用示例 1.1 实体类 1.2 dao方法 1.3 写Service / biz 三层架构 1.4 建action 相当于selvert 1.5 con连接MySQL 8.0 版本 1.6 配置文件 XML 1.7 主界面布局 1.8 增加界面布局 1.9 写tld配置文件 2.0 注意架包 我是已经打包好的 mymv…...

RabbitMQ 教程 | 第2章 RabbitMQ 入门
👨🏻💻 热爱摄影的程序员 👨🏻🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…...

双网卡如何配置DNS?我是一个仅主机模式配置静态(static)IP、一个NET或桥接(dhcp获取)
目录 一、所有主机初始化 二、135、136服务器,部署DNS调度服务器 1、更改主机主从DNS服务器的主机名称 2、安装bind软件、修改主配置文件 3、修改区域配置文件 4、修改数据文件 5、启动named服务、修改网卡信息 6、解析 7、双网卡的话记得注释以下内容、注…...

Android10: 动态隐藏导航栏和状态栏总结
(1)全屏相关设置 //(1)主题添加 <item name"android:windowFullscreen">true</item>//(2)setContentView之前添加 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCRE…...