搜索
bottom↓
回复: 0

【正点原子FPGA连载】第三十二章双目OV5640摄像头HDMI显示实验--摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南

[复制链接]

出0入234汤圆

发表于 2020-8-17 11:10:51 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2020-10-24 10:57 编辑

1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_linhanz.html
4)对正点原子FPGA感兴趣的同学可以加群讨论:876744900
QQ群头像.png
5)关注正点原子公众号,获取最新资料


100846rel79a9p4uelap24.jpg

100846f1ce1fg14zbg0va4.png

第三十二章双目OV5640摄像头HDMI显示实验



在“双目OV5640摄像头LCD显示实验”中,我们将双目摄像头采集的两路图像显示在LCD上,并在LCD屏上叠加字符。本章我们将使用领航者ZYNQ开发板实现对双目OV5640摄像头的图像采集并通过HDMI显示器实时显示。
本章包括以下几个部分:
3232.1简介
32.2实验任务
32.3硬件设计
32.4软件设计
32.5下载验证


32.1简介
Xilinx官方提供了专门用于视频混合显示和简单文本叠加的视频处理模块,即OSD(On Screen Display)IP核。关于该IP核的详细介绍请大家参考“双目OV5640摄像头LCD显示实验”。
32.2实验任务
本章的实验任务是通过调用OSD IP核,在领航者Zynq开发板上实现双目OV5640摄像头HDMI显示器的实时显示,并在HDMI显示器上叠加字符。
32.3硬件设计
我们的领航者Zynq开发板上有一个扩展接口(位于ATK MODULE附近),该接口可以用来连接双目OV5640摄像头,注意在连接的时候,双目OV5640摄像头的镜头方向朝外。另外需要说明的是,扩展口的引脚和开发板上的部分外设是复用的,因此当扩展口上连接双目OV5640摄像头时,开发板上复用至扩展口上的外设将不能使用。
根据实验任务我们可以画出本次实验的系统框图,如下图所示:
阿莫论坛发帖领航者专用1561.png

图 32.3.1 系统框图

图 32.3.1与“双目OV5640摄像头LCD显示实验”中的系统框图基本相同,只是将驱动LCD显示的rgb2lcd模块替换成了本次实验中的DVI Transmitter,用于驱动HDMI接口;另外还删除了用于读取LCD ID信息的AXI GPIO模块。因此本次实验的硬件设计部分在“双目OV5640摄像头LCD显示实验”的基础上稍作修改即可。
最终图中的数据流走向为:OV5640图像采集是我们自定义的IP核,负责将OV5640的数据转成视频流数据;视频流数据经过Video in to AXI4-Stream IP核转换成AXI4-Stream IP格式数据流,然后通过VDMA的写通道转成AXI4 Memory Map格式,并最终写入DDR内存中。VDMA通过AXI InterConnect IP核与AXI_HP端口进行连接,从而高效访问DDR3。由于本次实验是对双目OV5640摄像头进行图像采集和显示,因此OV5640图像采集IP核、Video In to AXI4-Stream IP核和VDMA IP核需要添加两次。
两路VDMA输出的AXI4-Stream格式的图像数据连接至OSD IP核,经OSD IP核拼接和叠加字符后,连接至AXI4-Stream to Video Out IP核。AXI4-Stream to Video Out IP核在VTC IP核的控制下,把AXI4-Stream格式的数据转换成视频输出的数据格式,并将输出的视频数据流连接至DVI Transmitter IP核的输入端。DVI Transmitter IP核是本次实验自定义的IP核,用于驱动HDMI接口。
首先要删除“双目OV5640摄像头LCD显示实验”工程中的rgb to lcd和AXI GPIO两个模块,以及LCD相关的接口。如下图所示,我们要删除图中橙色高亮的两个模块和3个接口:
阿莫论坛发帖领航者专用11443.png

图 32.3.2 删除LCD相关模块

接下来添加DVI Transmitter IP核。该IP核位于工程目录下的ip_repo文件夹中,名为“DVI_TX”。我们需要将其添加到工程的IP库中,添加IP核的方法请大家参考“自定义IP核-呼吸灯实验”。添加完成后,我们要在Block Design中连接DVI Transmitter模块的接口信号,并引出外部端口,具体的连接方式如下图所示:
阿莫论坛发帖领航者专用11682.png

图 32.3.3 添加并连接DVI_Transmitter IP核

Block Design修改完成后保存,然后重新Generate Output Products。接下来我们还要修改约束文件,为HDMI接口分配引脚。打开工程中名为“system_wrapper.xdc”的约束文件,并将原先LCD相关的约束语句删除,替换成以下内容:
  1. set_property -dict {IOSTANDARD TMDS_33                 } [get_ports TMDS_tmds_clk_n]
  2. set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN L14} [get_ports TMDS_tmds_clk_p]
  3. set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN K19} [get_ports {TMDS_tmds_data_p[0]}]
  4. set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[0]}]
  5. set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN M14} [get_ports {TMDS_tmds_data_p[1]}]
  6. set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[1]}]
  7. set_property -dict {IOSTANDARD TMDS_33  PACKAGE_PIN L16} [get_ports {TMDS_tmds_data_p[2]}]
  8. set_property -dict {IOSTANDARD TMDS_33                 } [get_ports {TMDS_tmds_data_n[2]}]
  9. set_property -dict {IOSTANDARD LVCMOS33 PACKAGE_PIN G17} [get_ports tmds_oen]
复制代码

保存约束文件,然后选择“Generate Bitstream”重新生成BIT文件。
在生成Bitstream之后,在菜单栏中选择 File > Export > Export hardware导出硬件,并在弹出的对话框中,勾选“Include bitstream”。然后在菜单栏选择File > Launch SDK,启动SDK软件。
32.4软件设计
本次实验的软件工程与“双目OV5640摄像头LCD显示实验”略有不同,如下图所示:
阿莫论坛发帖领航者专用12904.png

图 32.4.1 软件工程

图 32.4.1左侧红色方框中的文件夹名为“display_ctrl_hdmi”,它在前面实验中“display_ctrl”的基础上删除了GPIO相关的函数及变量。在本次实验中删除了AXI GPIO模块,因此要删除这些函数和变量,否则会报错。
本次实验的代码如下所示:
  1. 1  #include <stdio.h>
  2. 2  #include <stdlib.h>
  3. 3  #include <string.h>
  4. 4  #include "xil_types.h"
  5. 5  #include "xil_cache.h"
  6. 6  #include "xparameters.h"
  7. 7  #include "xaxivdma.h"
  8. 8  #include "xaxivdma_i.h"
  9. 9  #include "display_ctrl_hdmi/display_ctrl.h"
  10. 10 #include "vdma_api/vdma_api.h"
  11. 11 #include "emio_sccb_cfg/emio_sccb_cfg.h"
  12. 12 #include "ov5640/ov5640_init.h"
  13. 13 #include "osd/osd.h"
  14. 14
  15. 15 //宏定义
  16. 16 #define FRAME_BUFFER_NUM   3                           //帧缓存个数3
  17. 17 #define DYNCLK_BASEADDR    XPAR_AXI_DYNCLK_0_BASEADDR  //动态时钟基地址
  18. 18 #define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID    //VDMA器件ID
  19. 19 #define DISP_VTC_ID        XPAR_VTC_0_DEVICE_ID        //VTC器件ID
  20. 20
  21. 21 //全局变量
  22. 22 //frame buffer的起始地址
  23. 23 unsigned int frame_buffer_addr[DISPLAY_VDMA_NUM];
  24. 24 unsigned int vdma_id[DISPLAY_VDMA_NUM] = {XPAR_AXIVDMA_0_DEVICE_ID,
  25. 25                                        XPAR_AXIVDMA_1_DEVICE_ID};
  26. 26
  27. 27 XAxiVdma     vdma[DISPLAY_VDMA_NUM];
  28. 28 DisplayCtrl  dispCtrl;
  29. 29 VideoMode    vd_mode;
  30. 30
  31. 31 int main(void)
  32. 32 {
  33. 33  u32 status0,status1;
  34. 34  u16 cmos_h_pixel;   //ov5640 DVP 输出水平像素点数
  35. 35  u16 cmos_v_pixel;   //ov5640 DVP 输出垂直像素点数
  36. 36  u16 total_h_pixel;  //ov5640 水平总像素大小
  37. 37  u16 total_v_pixel;  //ov5640 垂直总像素大小
  38. 38
  39. 39  cmos_h_pixel = 1024;//设置OV5640输出分辨率为1024*600
  40. 40  cmos_v_pixel = 600;
  41. 41  total_h_pixel = 2200;
  42. 42  total_v_pixel = 1000;
  43. 43
  44. 44  emio_init();                                //初始化EMIO
  45. 45  status0 = ov5640_init(CMOS_CH0,cmos_h_pixel,//初始化ov5640 0
  46. 46                        cmos_v_pixel,
  47. 47                       total_h_pixel,
  48. 48                       total_v_pixel);
  49. 49  status1 = ov5640_init(CMOS_CH1,cmos_h_pixel,//初始化ov5640 1
  50. 50                        cmos_v_pixel,
  51. 51                       total_h_pixel,
  52. 52                       total_v_pixel);
  53. 53  if(status0 == 0 && status1 == 0)
  54. 54      xil_printf("Dual OV5640 detected successful!\r\n");
  55. 55  else
  56. 56      xil_printf("Dual OV5640 detected failed!\r\n");
  57. 57
  58. 58  vd_mode = VMODE_1024x600;
  59. 59
  60. 60  for(u8 i=0;i<DISPLAY_VDMA_NUM;i++){
  61. 61      frame_buffer_addr = XPAR_PS7_DDR_0_S_AXI_BASEADDR+0x1000000*i;
  62. 62      //配置VDMA
  63. 63      run_vdma_frame_buffer(&vdma, vdma_id, vd_mode.width/2, vd_mode.height,
  64. 64                              frame_buffer_addr,0,0,BOTH);
  65. 65  }
  66. 66  //OSD初始化
  67. 67  osd_init(0x1016,vd_mode.width,vd_mode.height);
  68. 68  //初始化Display controller
  69. 69  DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
  70. 70  //设置VideoMode
  71. 71  DisplaySetMode(&dispCtrl, &vd_mode);
  72. 72  DisplayStart(&dispCtrl);
  73. 73
  74. 74     return 0;
  75. 75 }
复制代码

可以看出,本次实验的程序与“双目OV5640摄像头LCD显示实验”非常相似。首先删除了读取LCD ID相关的内容,然后将摄像头的输出分辨率固定改成1024*600。有关这部分代码的详细介绍请大家参考“双目OV5640摄像头LCD显示实验”,此处不再赘述。
32.5下载验证
首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将USB UART接口与电脑连接,用于串口通信。使用HDMI连接线将HDMI显示器连接到领航者底板上的HDMI接口。双目OV5640摄像头连接底板上的扩展口连接(扩展口位于ATK_MODULE旁边,连接时双目摄像头镜头方向朝外),如下图所示。最后连接开发板的电源,并打开电源开关。
阿莫论坛发帖领航者专用15982.png

图 32.5.1 双目摄像头镜头方向朝外

在SDK软件下方的SDK Terminal窗口中点击右上角的加号设置并连接串口。然后下载本次实验硬件设计过程中所生成的BIT文件,来对PL进行配置。最后下载软件程序,下载完成后,在下方的SDK Terminal中可以看到应用程序打印的信息,打印的信息如下图所示:
阿莫论坛发帖领航者专用16181.png

图 32.5.2 串口终端中打印的信息

从串口打印的信息可以看出硬件连接的状态和OSD配置的状态。此时HDMI显示器实时显示两路摄像头的视频图像,并且在每一路摄像头的上方叠加了字符串,分别为“OV5640 1”和“OV5640 2”,HDMI显示器显示画面如下图所示:
阿莫论坛发帖领航者专用16362.png

图 32.5.3 HDMI显示器显示画面

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 09:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表