[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_SDK高级篇连载-12双摄像头采集显示方案(FDMA)

文档创建者:FPGA课程
浏览次数:79
最后更新:2024-10-08
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-SOC » 1_SDK应用方案(仅旗舰型号) » 2-SDK高级应用方案
本帖最后由 FPGA课程 于 2024-10-8 09:08 编辑

​软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
米联客uifdma是基于AXI4总线接口开发的一种DMA数据管理IP,该IP可以统一视频数据、普通ADC数据、PLDDR接口和PSDDR接口,具有更加广泛的通用性。并且该IP是米联客对所有开发者开源的。
关于FEP-GPIO-CEPX3扩展卡介绍请阅读“附录1”。
关于OV5640摄像头介绍请阅读“附录1”。
关于VDMA IP的使用请阅读“附录2”
本文实验目的:
1:掌握ui-fdma和ui_fdmadbuf在视频采集方案的应用
2:掌握多个AXI-FDMA同时传输视频的同步解决方法
3:掌握uifdma_dbuf视频格式中Stride参数的使用
4:掌握uifdma_dbuf和VDMA之间如何进行帧同步,如何实现3帧图形缓存,确保图形不撕裂。
2系统框图
e12046e864d24fe686c18e8a457972e1.jpg
3硬件电路分析
硬件接口和子卡模块请阅读“附录1”
配套工程的FPGA PIN脚定义路径为soc_prj/uisrc/04_pin/ fpga_pin.xdc。
4搭建SOC系统工程
4.1PL图形化编程
图片1.jpg
上图中高亮部是FDMA的帧同步计数器,CAM0的帧同步计数器提供给CAM1使用。
另外,我们对CAM0和CAM1的IP在BD图像模块中做了层级封装,这样可以让复杂的BD图像设计,看起来更加简洁,如下图所示。
image.jpg

image.jpg

这个技巧如下,选中需要层级封装的IP,右击选择Create Hierarchy
8335ab38258e499ea28a6facc54b92c2.jpg
1:CAM0中FDMA IP设置
关键设置:
1`WBaseaddr 0x10000000 设置缓存的起始地址
2`WDsizebits 设置缓存的大小,2^23次方代表8MB大小
3`WBufsize 设置图像采用三缓存
4`WXsize设置行像素640
5`WXStride设置行Stride参数为1280,改参数用于2个视频在一个显存中显示
6`WYsize设置场像素为480
21e780e0a149476b954ef7302d099312.jpg
2:CAM1FDMA IP设置
1`WBaseaddr 0x1012CA00 设置缓存的起始地址,通过设置该地址可以让图像在指定的偏移位置显示
2`WDsizebits 设置缓存的大小,2^23次方代表8MB大小
3`WBufsize 设置图像采用三缓存
4`WXsize设置行像素640
5`WXStride设置行Stride参数为1280,改参数用于2个视频在一个显存中显示
6`WYsize设置场像素为480
dfb28d28fcf0451c90d80d0dbaf15a8f.jpg
3:多路视频同屏显示原理
3b582feef3544fb68997dad17452ae55.jpg
为了把2个图像显示到1个显示器,首先得搞清楚以下关系:
hsize:每1行图像实际在内存中占用的有效空间,以32bit表示一个像素的时候占用内存大小为hsize*4
hstride:用于设置每行图像第一个像素的地址,以32bit 表示一个像素的时候h_cnt* hstride*4
vsize:有效的行
因此很容易得出cam0的每行第一个像素的地址也是h_cnt* hstride*4
同理如果我们需要把cam1在hsize和vsize空间的任何位置显示,我们只要关心cam1每一行图像第一个像素的地址,可以用以下公式h_cnt* hstride*4+offset
比如我们这里背景输出到显示器的分辨率为1280*720,cam1的分辨率是640*480需要移动上图的右下脚,offset=(1280-640)*4*(720-480)
4:视频输出VDMA IP设置
8dcfba0861e24b2097a84ee35687c989.jpg
以下设置视频输出VDMA为从模式,帧同步跟随主模式的CAM0/uifdma_dbuf
92c88734d6a04d4c9afd86ee17cc14ad.jpg
4.2设置地址分配
以sccb方式初始化摄像头的地址空间截图
c12e09a410704648b9c7a6d90bc27a69.jpg
4.3添加PIN约束
1:选中PROJECT  MANAGERà Add SourcesàAdd or create constraints,添加XDC约束文件。
e6fcb2ba6226499b8b935f85cf4c8f23.jpg
2:打开提供例程,复制约束文件中的管脚约束到XDC文件,或者查看原理图,自行添加管脚约束,并保存。
以下是添加配套工程路径下已经提供的pin脚文件。配套工程的pin脚约束文件在uisrc/04_pin路径
4.4编译并导出平台文件
1:单击Block文件à右键àGenerate the Output ProductsàGlobalàGenerate。
2:单击Block文件à右键à Create a HDL wrapper(生成HDL顶层文件)àLet vivado manager wrapper and auto-update(自动更新)。
3:生成Bit文件。
4:导出到硬件: FileàExport HardwareàInclude bitstream
5:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。
3308a284d1fc49ca8f7b6f0b52918567.jpg
5搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
5.1创建SDK Platform工程
7bb00d581f2d4e0eb30af7fd49111d03.jpg
5.2创建camx2_5640 APP测试工程
55d13913af56414e94b9151a0b54ff7e.jpg
6程序分析
6.1主程序分析
  1. /********************MILIANKE**************************
  2. *Company : MiLianKe Electronic Technology Co., Ltd.
  3. *WebSite:https://www.milianke.com
  4. *TechWeb:https://www.uisrc.com
  5. *tmall-shop:https://milianke.tmall.com
  6. *jd-shop:https://milianke.jd.com
  7. *taobao-shop1: https://milianke.taobao.com
  8. *Create Date: 2021/10/15
  9. *File Name: 5640_test.c
  10. *Description:
  11. *Declaration:
  12. *The reference demo provided by Milianke is only used for learning.
  13. *We cannot ensure that the demo itself is free of bugs, so users
  14. *should be responsible for the technical problems and consequences
  15. *caused by the use of their own products.
  16. *Copyright: Copyright (c) MiLianKe
  17. *All rights reserved.
  18. *Revision: 1.0
  19. ****************************************************/
  20. #include "xil_exception.h"
  21. #include "xil_printf.h"
  22. #include "xil_cache.h"
  23. #include "xgpio.h"
  24. #include "sccb_iic.h"
  25. #include "ov5640_cfg.h"
  26. #include "sys_intr.h"
  27. #include "HDMIdma_intr.h"
  28. #define BUF_BASE_SIZE   0x10000000//DDR中基地址
  29. #define BUF_RANG_SIZE          0x800000//每个FDMA缓存的地址偏移大小
  30. #define BUF1_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*0//图像基地址1
  31. #define BUF2_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*1//图像基地址2
  32. #define BUF3_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*2//图像基地址3
  33. u8 *VIDEOOUT_DBUF[BUFFERSIZE];
  34. extern XScuGic Intc; //GIC
  35. extern XHDMIDma HDMIDma;
  36. extern XHDMIPsu HDMIPsu;
  37. extern XAVBuf AVBuf;
  38. extern Run_Config RunCfg;
  39. #define VIDEO_OUT_VDMA_ID XPAR_AXI_VDMA_0_DEVICE_ID
  40. void init_intr_sys(void)
  41. {
  42.         Init_Intr_System(&Intc);//initialize global interrupt source
  43.         pl_intr_init(&Intc);
  44.         HDMIdma_init(&RunCfg ,&Intc);//setup HDMI channel
  45.         HDMIdma_Setup_Intr_System(&RunCfg);//enable HDMI channel
  46.         Setup_Intr_Exception(&Intc);//enable global interrupt source
  47. }
  48. XGpio rstn_5640;
  49. XGpio sscb_cam0;
  50. XGpio sscb_cam1;
  51. int main()
  52. {
  53.         u8 mode_s =0;
  54.         Xil_DCacheDisable();
  55.         Xil_ICacheDisable();
  56.         video_buffer_init(VIDEOOUT_DBUF[0]);//初始化HDMI中断
  57.         init_intr_sys();
  58.         VIDEOOUT_DBUF[0] = (u8*)BUF1_ADDR;
  59.         VIDEOOUT_DBUF[1] = (u8*)BUF2_ADDR;
  60.         VIDEOOUT_DBUF[2] = (u8*)BUF3_ADDR;
  61.         memset(VIDEOOUT_DBUF[0], 0x00, BUFFERSIZE);//初始化内存
  62.         memset(VIDEOOUT_DBUF[1], 0x00, BUFFERSIZE);
  63.         memset(VIDEOOUT_DBUF[2], 0x00, BUFFERSIZE);
  64.         Xil_DCacheFlushRange((INTPTR)VIDEOOUT_DBUF[0], BUFFERSIZE);
  65.         Xil_DCacheFlushRange((INTPTR)VIDEOOUT_DBUF[1], BUFFERSIZE);
  66.         Xil_DCacheFlushRange((INTPTR)VIDEOOUT_DBUF[2], BUFFERSIZE);
  67.         XGpio_Initialize(&rstn_5640, XPAR_GPIO_RSTN_DEVICE_ID);
  68.         XGpio_SetDataDirection(&rstn_5640, 1, 0x0);
  69.         XGpio_DiscreteWrite(&rstn_5640, 1, 0x0);
  70.         sccb_gpio_init(&sscb_cam0,XPAR_CAM0_GPIO_SCCB_DEVICE_ID);
  71.         sccb_gpio_init(&sscb_cam1,XPAR_CAM1_GPIO_SCCB_DEVICE_ID);
  72.         ov5640_init(sscb_cam0,640,480,0x46,0x07);
  73.         ov5640_init(sscb_cam1,640,480,0x40,0x01);
  74.         XGpio_DiscreteWrite(&rstn_5640, 1, 0x1);
  75.     while(1)
  76.     {
  77.             video_buffer_update(VIDEOOUT_DBUF[mode_s],&RunCfg);
  78.                        if(mode_s >=2 ) mode_s = 0;
  79.                        else mode_s ++;
  80.                        sleep(1);
  81.            }
  82.     return XST_SUCCESS;
  83. }
复制代码

由于采用uifdma_dbuf的参数实在PL图形化设计中配置好的,因此,在PS部分的代码非常简单。
6.2:OV5640的镜像参数
本文中的摄像头模块采用了最新的FEP-CEPX3-CARD模块,该模块2个摄像头是对称放置,为了让2个图像都是同一方向,需要把其中的一路图像设置镜像
        ov5640_init(sscb_cam0,640,480,0x46,0x07);        ov5640_init(sscb_cam1,640,480,0x40,0x01);
我们可以简单了解下OV5640和镜像相关的2个寄存器:
c477600c7f4d479c81e073eafca38b02.jpg
deccacdad0a44d74b6d9a0577e1691e6.jpg

以看出来,只是两个寄存器:0x3820控制上下翻转,0x3821控制左右翻转。
7双目采集方案演示
7.1硬件准备
需要注意这里的 MLK-H3-CZ08-7100FC,扩展卡默认使用 1.8V IO 配的也是 1.8V 的子卡和摄像头
e0124f201bfa42aeb24632fd4816be6b.jpg
7.2实验结果
45f0935f623f4fd4afb146dd83e417ff.jpg
本方案路径下也提供了开发板自带的 CEP 接口摄像头采集的 demo
e1284572e0134766a93899b8d3d4536f.jpg
2ff6ffd245bf4f9cbbf165595e55b905.jpg
20230724024159.jpg?origin_url=file%3A%2F%2F%2FC%3A%5CUsers%5CADMINI~1%5CAppData%5CLocal%5CTemp%5Cksohtml11988%5Cwps85.jpg&pos_id=9OBnIeW0
image.jpg
image.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则