[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_SDK高级篇连载-13摄像头拍照方案(FDMA+VDMA)

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

​软件版本: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_vbuf3.0 ip的使用,本文实现一个综合性的实验,把摄像头的数据以BMP格式保存到TF卡中。
本文实验目的:
1:掌握uifdma_vbuf3.0的地址空间分配方法
2:利用多缓存机制,把内存中的图像以BMP格式保存到TF卡
2系统框图
23483b28cd7242b3ad755cf769f37d17.jpg
3硬件电路分析
硬件接口和子卡模块请阅读“附录1”
配套工程的FPGA PIN脚定义路径为soc_prj/uisrc/04_pin/ fpga_pin.xdc。
4搭建SOC系统工程
4.1PL图形化编
image.jpg
以上代码中OV5640数据格式转为RGB888输入到uifdma_dbuf的写端口,经过uifdma_dbuf后进入fdma,之后通过AXI_interconnect 进入到ZYNQ DDR中。
SDK代码中,PS(ARM)读取内存中保存的摄像头采样数据,并且通过HDMI实时显示。当按下快门按键的时候,点亮开发板的LED,同时把内存中的数据以BMP格式保存到SD卡中 。
下面具体看下关键几个IP的参数设置
1:uifdma_dbuf设置
由于输入数据是视频数据流形式,所以需要使能视频传输功能,这里也只使用到了写通道,所以读通道也不需要使能。
一般对于摄像头采集,设置3帧缓存就够用。WBaseaddr缓存的基地址只要设置合适的值即可,这里设置0x08000000 =128MB,这样保留了低128MB给应用程序使用。
由于一幅图片的大小为1280*720*4= 3600Bytes 因此WDsizebits设置每个缓存的大小,2^23次方=8MBYTE够用。
在SDK中的地址空间分配对应如下:
#define BUF_BASE_SIZE    0x08000000
#define BUF_RANG_SIZE   0x800000
#define BUF1_ADDR BUF_BASE_SIZE + BUF_RANG_SIZE*0;
#define BUF2_ADDR BUF_BASE_SIZE + BUF_RANG_SIZE*1;
#define BUF3_ADDR BUF_BASE_SIZE + BUF_RANG_SIZE*2;
1477233b99194d708d46d9add14ea6ee.jpg
2:uiFDMA设置
Fdma的数据位宽可以设置128这样效率最高。
f227076bde954f898c069c035d50abe3.jpg
3:AXI Interconnect设置
设置FIFO可以增加数据的吞吐能力
2888d1838480474bb301383edf0f12e7.jpg
以上代码中,调用了米联客uispi7606 IP CORE采集模拟数据,并且把采集好的数据写入到uifdmadbuf中,为了方便实验中观察数据,把第八个通道的AD数据改成了计数器。实际项目中可以把这个替换成第八个通道的ADC数据。
4.2设置地址分配
需要注意uifdma_dbuf的axi-lite接口地址,这个地址我们会在SDK 代码中用到读寄存器。
b130a170823f47e5aad9809beae41cbf.jpg
4.3添加PIN约束
1:选中PROJECT  MANAGERà Add SourcesàAdd or create constraints,添加XDC约束文件。
caea63e1a991475a8aa8527113793d67.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平台。
176b2f907a444a319323e0ccf2bc2523.jpg
5搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
5.1创建SDK Platform工程
24953e0e9edc43d096bc52606b7ff86b.jpg
ZYNQ的SD1支持FAT文件系统,我们的ZYNQ SD1接到了TF卡上,因此可以把保存的图片放到TF卡中。为了使用文件系统,需要对库做一些设置:
c24b037dd0b5456ca94c4a908d9ce176.jpg
5.2创建photograph_fdma——工程
81044ad3ca8e45dca818cf0ebeb2e8b1.jpg
6SDK程序分析
6.1 cam_photograph.c主程序
1:uifdma_dbuf 设置的地址空间
为了可以把uifdma_dbuf写入到DDR指定地址的数据读出来,首先需要对地址进行定义
  1. #define VIDEO_OUT_HSIZE         1280*4
  2. #define VIDEO_OUT_STRIDE 1280*4
  3. #define VIDEO_OUT_VSIZE         720
  4. #define IMG_SIZE VIDEO_OUT_HSIZE*VIDEO_OUT_VSIZE
  5. #define BUF_BASE_SIZE   0x10000000
  6. #define BUF_RANG_SIZE          0x800000
  7. #define BUF1_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*0;
  8. #define BUF2_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*1;
  9. #define BUF3_ADDR                BUF_BASE_SIZE + BUF_RANG_SIZE*2;
  10. u8 *UIFDMA_DBUF[IMG_SIZE] __attribute__ ((aligned(256)));
复制代码

2:指针数字指向三个缓存地址
给分配的内存指针数字指向FPGA中uifdma_dbuf中设置的地址空间:
  1. UIFDMA_DBUF[0] = (u8*)BUF1_ADDR;
  2. UIFDMA_DBUF[1] = (u8*)BUF2_ADDR;
  3. UIFDMA_DBUF[2] = (u8*)BUF3_ADDR;
复制代码

3:设置VDMA的地址
  1. video_out_ReadCfg.FrameStoreStartAddr[0] = (INTPTR)UIFDMA_DBUF[0];
  2. video_out_ReadCfg.FrameStoreStartAddr[1] = (INTPTR)UIFDMA_DBUF[1];
  3. video_out_ReadCfg.FrameStoreStartAddr[2] = (INTPTR)UIFDMA_DBUF[2];
复制代码

4:启动采集和停止采集
  1. XGpio_DiscreteWrite(&rstn_5640, 1, 0x1);//启动采集
  2. XGpio_DiscreteWrite(&rstn_5640, 1, 0x0);//停止采集
复制代码

5:本方案核心程序
核心程序中,不停读取按键的状态,当由按键按下,则当VDMA中断产生后,立马开始保存图片,这样做的目前是未来更好让图形静止在显示器中,模拟相机的拍照状态。另外在开发板上会有一个LED在保存图片的时候常亮。如果按键没有按下,则实时显示当前的摄像头图像。
  1. while(1){
  2.             delay_cnt =0;
  3.             if(button_down() && cap_button == 0)//read button when button io is 0 enable img grap
  4.                     cap_button =1;
  5.             else if(wfram1_cap_done == 1)//wait vmda s2mm write channel intrrupt
  6.             {
  7.                     XGpio_DiscreteWrite(&rstn_5640, 1, 0x0);//stop camera
  8.                     XGpio_DiscreteSet(&button_led, 1, AXI_GPIO_BIT1);//open led
  9.                     //set img name
  10.                     img_cnt++ ;
  11.                     sprintf(imgName, "%04u.bmp", img_cnt) ;
  12.                         printf("Write to SD Card...\r\n") ;
  13.                         //frush cache data all into ddr
  14.                         Xil_DCacheInvalidateRange((INTPTR) UIFDMA_DBUF[fdma_buf], IMG_SIZE) ;
  15.                         //write img to sdcard
  16.                         bmp_write(imgName, (char *)&BMODE_1280x720, (char *)UIFDMA_DBUF[fdma_buf], VIDEO_OUT_STRIDE) ;
  17.                         printf("Successfully Take img, img Name is %s\r\n", imgName) ;
  18.                         XGpio_DiscreteClear(&button_led, 1, AXI_GPIO_BIT1);//close led
  19.                         cap_button =0;//clear for next
  20.                         wfram1_cap_done =0;//clear for next
  21.                     XGpio_DiscreteWrite(&rstn_5640, 1, 0x1);//restar camera
  22.             }
  23.     }
复制代码

6.2pl_intr.c程序
该程序中响应来自uifdma_dbuf的中断,每当一帧图形发送完毕即产生一次PL中断,在PL中断中读取uifdma_dbuf的当前缓存号
  1. void PS_RX_intr_Handler(void *param)
  2. {
  3.         fdma_buf = Xil_In32((UINTPTR)FDMA_DBUF_BASE_ADDR);
  4. }
复制代码

7方案演示
7.1硬件准备
本实验需要用到 JTAG 下载器、USB 转串口外设,另外需要把核心板上的 2P 模式开关设置到 JTAG 模式,即 ON ON (注意新版本的 MLK-H3-CZ08-7100FC(米联客 7X 系列),支持 JTAG 模式,对于老版本的核心板,JTAG 调试 的时候一定要拔掉 TF 卡,并且设置模式开关为 OFF OFF)
2605b1cc7f18421583470ce80ee7b8ac.jpg
7.2实验结果
按下按键拍照,拍照当前照片静止
3c66b220d3e14d7da0cd24d12c0ab33e.jpg
用读卡器读取TF卡保存的图片
b223c7c4933c4e66b38c46a4c92f132c.jpg
可以看到我们录制的视频中拍照的结果对比
1297b610812e47d4b0190e4c26abcc71.jpg
本实验也提供了 CEPX3,双目摄像头的采集方案
a458df82d1e54240be642bb24c3b58ac.jpg
图片1.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则