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…...
OpenClaw+Qwen3.5-9B:技术文档翻译与本地化自动化
OpenClawQwen3.5-9B:技术文档翻译与本地化自动化 1. 为什么选择这个技术组合? 去年参与一个开源项目时,我遇到了文档本地化的难题。项目文档有300多页Markdown文件,需要翻译成5种语言。传统翻译工具要么破坏格式,要么…...
wUU代码混淆实战指南:使用Obfuscar构建坚不可摧的安全防线
在当今数字化时代,保护.NET应用程序的源代码安全变得尤为重要。你是否担心自己的知识产权被轻易窃取?是否希望防止竞争对手通过反编译分析你的核心业务逻辑?今天,我将为你详细介绍一款强大的开源混淆工具——Obfuscar,…...
引爆企业降本增效的AI革命!生成式AI应用专家亲授,从字节跳动到华为的数字化转型实战秘籍!
本文介绍了资深AI专家Mr. Li在生成式AI应用与数字化转型领域的丰富经验,涵盖其在华为、字节跳动等企业的实践经历,以及在多个国家级标准制定和央企数字化转型项目中的参与。Mr. Li提供了一系列关于生成式AI和企业数字化转型的精品课程,旨在帮…...
NineData SQL AI 智能补全上线:写 SQL,不必每次都从头敲
写 SQL 的人,大概都遇到过这种情况: 明明脑子里已经知道要查什么,但真正开始写的时候,还是得一点点补关键字、补表名、补字段、补语句结构。越是多表查询、长 SQL、复杂条件,越容易写得慢、改得烦,还容易漏…...
WPF高性能绘图避坑指南:为什么你的心电图曲线会让CPU飙升?
WPF高性能绘图避坑指南:为什么你的心电图曲线会让CPU飙升? 在医疗监护设备或金融行情系统中,实时波形渲染的卡顿可能直接导致误诊或交易延迟。当你的WPF应用在绘制每秒60帧的心电图时突然出现CPU占用率突破90%,这往往不是硬件性能…...
医疗AI实战:如何用NLP技术从电子病历中提取科研特征(附Python代码)
医疗AI实战:从电子病历中挖掘科研金矿的NLP技术指南 在医疗健康领域,电子病历(EMR)是一座尚未充分开发的数据金矿。据统计,医疗机构产生的数据中超过70%是非结构化文本信息,包括医生记录、检查报告和病程描…...
ABB机器人X6-WAN口多协议共存实战:NFS、Socket、RobotStudio与Profinet如何和谐共处?
ABB机器人X6-WAN口多协议共存实战:NFS、Socket、RobotStudio与Profinet如何和谐共处? 在工业自动化领域,ABB机器人系统的网络配置一直是工程师们关注的焦点。特别是当我们需要在单个X6-WAN口上同时运行NFS文件传输、Socket通信、RobotStudio远…...
DocHub二次开发指南:自定义功能扩展与API集成
DocHub二次开发指南:自定义功能扩展与API集成 【免费下载链接】DocHub 参考百度文库,使用Beego(Golang)开发的开源文库系统 项目地址: https://gitcode.com/gh_mirrors/do/DocHub DocHub是基于Beego框架(Golang…...
Linux日志高效搜索:从基础grep到journalctl实战技巧
1. Linux日志搜索:运维工程师的必备技能 每次服务器出现异常,第一反应是什么?没错,就是查日志。作为在Linux系统摸爬滚打多年的老运维,我见过太多新手面对海量日志时的手足无措。其实日志排查就像破案,关键…...
HoRain云--Julia运算符全解析
🎬 HoRain云小助手:个人主页 🔥 个人专栏: 《Linux 系列教程》《c语言教程》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!…...
