RISC-V MCU中文社区

【分享】 蜂鸟处理器+OV5640摄像头模块开发

发表于 全国大学生集成电路创新创业大赛 2021-05-10 23:51:50
26
8426
16

本队伍编号CICC3042,本文重点介绍蜂鸟处理器和OV5640模块的结合方式、OV5640的窗口调节,以及图像的resize方法,试图以一种简单快速的方式得到令人满意的OV5640的输出图像,为进一步的图像处理做准备。


我们首先实现了摄像头采集模块和HDMI显示模块,随后将二者与蜂鸟结合,结合方式如下所示,虚线框中为我们添加的部分,同时对蜂鸟原来的外设进行裁剪,仅保留需要的部分。这里OV5640HDMI模块成为蜂鸟的外设,可以由处理器控制启动,并进行少量配置。同时为了降低开发难度,二者的很多配置是固定的,通过verilog硬件模块初始化,不受处理器控制,这样的优点是初始化速度快、降低了软硬件开发难度;缺点是缺少配置灵活性,不能在运行时修改配置,但是在一个工程中摄像头的配置经常是固定的,因此缺点带来的损失并不大。


摄像头模块和HDMI模块的具体结构如下,OV5640的寄存器配置保存在查找表中,Reg Config模块上电后自动将寄存器配置通过I2C接口发送给摄像头;Frame Capture提供摄像头的时钟驱动,并接收其采集的RGB数据,写到FIFO中,FIFO实现两个不同时钟模块的数据通信;我们实现了通过AXI接口直接访问DDRDMA模块,包括读写两个通道,摄像头采集的数据通过写通道写入DDR,而HDMI显示模块通过读通道将DDR的数据显示到屏幕上;LCD Driver根据显示分辨率生成HDMIVGA时序驱动;HDMI Out模块为Digilent提供的IP,其输出引脚直接接到HDMI接口上;Controller模块提供系统工作的状态机,控制两个模块的运行。


接下来介绍OV5640摄像头模块,可以参考OV5640 datasheet,这里推荐CrazyBingo提供的教程 http://crazyfpga.com/


在实际工程中,我们可能需要调节输出窗口大小,OV5640 datasheet中给出了设置采样窗口大小的寄存器,如下图所示。进行窗口设置的寄存器为0x3800-0x3813

由下图得知0x38080x38090x380A0x380B决定了最终输出的窗口大小,一般情况下我们只需要改动这四个寄存器的值即可调节输出窗口。


上述调节窗口的方法用于简单调节,其本质上是在采样的原图基础上直接裁剪,仅得到了原图的一部分,因此显示器输出也是原图的一部分。有时我们希望显示器的显示范围更大或者更加灵活,可以将摄像头采集的图像经过resize后保存,两种方法的区别如下图所示:


这时为了方便地实现resize,可以利用Vivado HLS,具体为hls_video.h中的hls::Resize函数或hls::Resize_opr_linear函数,数据端口综合为axi-stream接口,顶层函数代码如下:


void resize(hls::stream > &in, hls::stream > & out) {

#pragma HLS INTERFACE axis port=in

#pragma HLS INTERFACE axis port=out

 

#pragma HLS dataflow

    hls::Mat raw_img;

    hls::Mat resize_img;

    stream_to_mat(in, raw_img);

//    hls::Resize(raw_img, resize_img, HLS_INTER_LINEAR);

    hls::Resize_opr_linear(raw_img, resize_img);

    mat_to_stream(resize_img, out);

}


生成的模块如下:

将其连接到Frame CaptureWrite FIFO之间即可,这种连接方式在摄像头采集数据的同时进行处理,因为摄像头的帧率有限,resize模块的处理时间足够,所以不会影响性能。实际测试发现采集的图像具有较好的视野范围,并且可以随意修改输出图片大小。


喜欢16
用户评论 (26)
  • 突刺咸鱼

    2021-06-13 15:17:29 突刺咸鱼 1#

    王翔

    因为摄像头和HDMI都有接口需要分配到引脚上,我在顶层例化了这两个模块,然后把总线的接口一层层接出来和他们连接

    大佬,你们的摄像头和HDMI的接口用的是GPIOB的接口吗,你们最后是直接把GPIOB的那几个需要用的引脚去掉了,还是在哪一个模块里面将他们和GPIOB的口子相连接了呢?我看代码里面有IOBUF,然后通过这个BUF一直连到了e203_subsys_perips这个文件里面。

  • 突刺咸鱼

    2021-05-25 13:18:14 突刺咸鱼 2#

    王翔

    和其他外设一个道理,比如uart模块也挂在总线上,它的tx和rx接到gpio上

    哦哦,意思就是你们把HDMI模块挂在总线上,同时也把他的接口接在了GPIO上的吧……谢谢大佬

  • 王翔

    2021-05-25 13:03:12 王翔 3#

    突刺咸鱼

    没事...大佬,趁你有时间我还想问问,你的HDMI模块的多个接口不是连接到空的GPIO上定义的吗?你是直接在挂到了总线上吗?

    和其他外设一个道理,比如uart模块也挂在总线上,它的tx和rx接到gpio上

  • 突刺咸鱼

    2021-05-25 11:20:59 突刺咸鱼 4#

    王翔

    对的是这样,抱歉回复太晚了

    没事...大佬,趁你有时间我还想问问,你的HDMI模块的多个接口不是连接到空的GPIO上定义的吗?你是直接在挂到了总线上吗?

  • 王翔

    2021-05-24 11:34:21 王翔 5#

    突刺咸鱼

    就相当于你那个大的模块一边是总线,一边是I2C吗,不过I2C的时序是自己实现的,是这个意思吗,大佬,我还想问一下,外设总线的时序其实和icb总线是一样的把,就比如我接了一个模块在外设总线上,然后可以根据icb总线写接口时序,在把它实例化到顶层模块上,是这样理解吗,,谢谢

    对的是这样,抱歉回复太晚了

  • 突刺咸鱼

    2021-05-16 16:36:44 突刺咸鱼 6#

    王翔

    因为摄像头和HDMI都有接口需要分配到引脚上,我在顶层例化了这两个模块,然后把总线的接口一层层接出来和他们连接

    就相当于你那个大的模块一边是总线,一边是I2C吗,不过I2C的时序是自己实现的,是这个意思吗,大佬,我还想问一下,外设总线的时序其实和icb总线是一样的把,就比如我接了一个模块在外设总线上,然后可以根据icb总线写接口时序,在把它实例化到顶层模块上,是这样理解吗,,谢谢

  • 王翔

    2021-05-16 16:19:09 王翔 7#

    突刺咸鱼

    我还想问一下,你的摄像头和HDMI模块是实例化进入哪一个文件啊,是直接挂载外设总线上吗。。麻烦了大佬

    因为摄像头和HDMI都有接口需要分配到引脚上,我在顶层例化了这两个模块,然后把总线的接口一层层接出来和他们连接

  • 王翔

    2021-05-16 16:15:47 王翔 8#

    突刺咸鱼

    大佬,我想问下你的摄像头用的I2C接口吗?那么数据的存取都是在对应的给予的I2C地址上应用吧,也就是I2C0(0x1002_5000-0x1002_5fff)或者I2C1(0x1003_5000-0x1003_5fff)吗??

    摄像头的I2C时序是自己实现的,没有用蜂鸟的I2C接口

  • 突刺咸鱼

    2021-05-16 16:05:23 突刺咸鱼 9#

    突刺咸鱼

    大佬,我想问下你的摄像头用的I2C接口吗?那么数据的存取都是在对应的给予的I2C地址上应用吧,也就是I2C0(0x1002_5000-0x1002_5fff)或者I2C1(0x1003_5000-0x1003_5fff)吗??

    我还想问一下,你的摄像头和HDMI模块是实例化进入哪一个文件啊,是直接挂载外设总线上吗。。麻烦了大佬

  • 突刺咸鱼

    2021-05-16 16:02:02 突刺咸鱼 10#

    王翔

    关于按键不需要任何关于取反的修改,板子的reset按键按下是低电平,连到fpga_rst上;普通按键按下是高电平,连到wakeup信号上。如果怀疑是自己的引脚分配有问题,第一代蜂鸟里给出了arty开发板的移植,可以仔细对比一下。

    大佬,我想问下你的摄像头用的I2C接口吗?那么数据的存取都是在对应的给予的I2C地址上应用吧,也就是I2C0(0x1002_5000-0x1002_5fff)或者I2C1(0x1003_5000-0x1003_5fff)吗??

  • 悟空

    2021-05-12 18:00:06 悟空 11#

    王翔

    关于按键不需要任何关于取反的修改,板子的reset按键按下是低电平,连到fpga_rst上;普通按键按下是高电平,连到wakeup信号上。如果怀疑是自己的引脚分配有问题,第一代蜂鸟里给出了arty开发板的移植,可以仔细对比一下。

    可是我的开发板按键按下是高电平,何mcu的不一样,所以得取反吧

  • 王翔

    2021-05-12 17:07:22 王翔 12#

    悟空

    大佬你好,我试了下还是不行,我就把e203的mcu_jtag,两个gpio_tx,rx(连接到pmod),还有复位信号我变成一个高有效信号,内部soc例化时候取反,然后就是mcu_wakeup信号接到一个高有效按键上(也取反了)。其他soc信号我没接出来,想问下你还有其他的步骤吗

    关于按键不需要任何关于取反的修改,板子的reset按键按下是低电平,连到fpga_rst上;普通按键按下是高电平,连到wakeup信号上。如果怀疑是自己的引脚分配有问题,第一代蜂鸟里给出了arty开发板的移植,可以仔细对比一下。

  • 悟空

    2021-05-12 15:20:28 悟空 13#

    王翔

    理论上是可以的,图上画出了STARTUP对应的模块把USRCCLKO连到了flash的CLK上,这是原语完成的不需要我们分配引脚。我在nexys4 ddr上试过可以,但是同样的方法在nexys video上没成功,期待你在genesys2上的结果~

    大佬你好,我试了下还是不行,我就把e203的mcu_jtag,两个gpio_tx,rx(连接到pmod),还有复位信号我变成一个高有效信号,内部soc例化时候取反,然后就是mcu_wakeup信号接到一个高有效按键上(也取反了)。其他soc信号我没接出来,想问下你还有其他的步骤吗

  • 王翔

    2021-05-12 11:37:40 王翔 14#

    悟空

    请问一下大佬,我移植到genesys2开发板上没有qspi0_sck管教,看网上添加STARUPE2原语,里面USRCCLKO我是接的soc顶层出来的qspi0_sck信号,(我就把原来system的output qspi0_sck替换成wire)这样就可以吗,想请教下它不指定管教是怎么连接到我的flash上的呢,如下图


    preview

    理论上是可以的,图上画出了STARTUP对应的模块把USRCCLKO连到了flash的CLK上,这是原语完成的不需要我们分配引脚。我在nexys4 ddr上试过可以,但是同样的方法在nexys video上没成功,期待你在genesys2上的结果~

  • 悟空

    2021-05-12 10:39:58 悟空 15#

    悟空

    嗯嗯,多谢了!!

    请问一下大佬,我移植到genesys2开发板上没有qspi0_sck管教,看网上添加STARUPE2原语,里面USRCCLKO我是接的soc顶层出来的qspi0_sck信号,(我就把原来system的output qspi0_sck替换成wire)这样就可以吗,想请教下它不指定管教是怎么连接到我的flash上的呢,如下图


    preview

王翔

王翔 实名认证

懒的都不写签名

积分
问答
粉丝
关注
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板