请选择 进入手机版 | 继续访问电脑版
[X]关闭

基于ZYNQ的OV5640图像采集+LCD显示测试(RGB 接口、HDMI接口屏)

文档创建者:mlink_fae
浏览次数:11316
最后更新:2024-03-09
 
本帖最后由 mlink_fae 于 2019-8-8 15:01 编辑

      在实际开发中,我们会经常使用到LCD屏,LCD屏的种类有很多种,对应的使用方法也有所不同,但是,在ZYNQ 图像传输开发中,思路大体类似,下面介绍在ZYNQ中,使用LCD显示OV5640图像方法。
1.1 概述
    下面向大家介绍了在ZYNQ开发板上实现OV5640数据采集在LCD屏显示功能。
    测试使用模块:OV5640摄像头,LCD (RGB或HDMI接口) 屏,米联客ZYNQ开发板。
    这里需要说明LCD屏的分辨率是1024x600,OV5640使用的分辨率是640X480。
测试工程是在摄像头采集的测试工程的基础上进行修改,下面仅说明区别,其他相同的部分,这里不在赘述。

1.2 硬件工程
     总体来说,搭建LCD显示的工程架构同之前搭建OV5640 HDMI显示的工程类似,采集输入端、VDMA处理、显示输出端,这里变化的是显示输出端。
     为了做对比,我分别做了RGB /HDMI 接口LCD屏的640x480、640x480_1024x600测试历程。这里使用缩放IP,将640x480分辨率图像放大到1024x600。


LCD
测试工程
LCD(RGB接口)
640x480

640x480_1024x600 (使用缩放ip)
LCD(HDMI接口)
640x480

640x480_1024x600 (使用缩放ip)


1.2.1 硬件平台搭建

1、VTC设置
         由于LCD屏是1024x600,对于VTC中没有现成的参数配置,因此,这里我们使用AXI4总线对VTC分辨率进行配置。
生成后的IP
选择自动连线,将VTC连接到总线上。然后,如图所示连接,并将s_axi_aclken给定值1。


2、ZYNQ 时钟设置

      ZYNQ IP 提供的FCLK_CLK0用于AXI 数据传输的时钟,这个时钟给定值要根据数据传输情况给定,不能设置太高也不能设置太低,否则会造成数据的堵塞,不会输出。通常我这里调试,640X480输出会给100M,1080P输出会给155M(实际输出是150M)。具体参考程序。



3、缩放IP设置

      OV5640的有几种分辨率(640x480、720P),而LCD屏的分辨率是1024x600;如果直接使用5640的分辨率显示,使用640X480输出,则不会铺满整个LCD屏;或者使用720P输出,则720P分辨率大于1024x600,则LCD不能显示5640采集的全部图像;因此,使用了hls封装的缩放IP,可以将输出的分辨率调整为LCD屏分辨率1024x600。
       使用的硬件工程,在OV5640 VDMA图像传输的基础上进行修改。将HLS生成的IP添加工程中,将Video In to AXI4-Stream的输出接口与HLS IP的输入接口连接,HLS IP的输出接口与VDMA的AXIS接口连接。

4、LCD接口设置

         HDMI接口:对于HDMI接口的LCD屏,Video Out IP后面接HDMI_FPGA_ML IP,将RGB信号转换为HDMI信号输出。
        RGB接口:对于RGB接口的LCD屏,Video Out IP信号直接输出,这个IP输出的是RGB信号,同事需要注意,对驱动LCD屏的其他信号,如时钟、使能信号进行配置。
1.2.2 SDK工程
640x480显示工程对应的main.c主函数


#include "I2C_16bit.h"
#include "xiicps.h"
#include "xil_io.h"
#include "xparameters.h"
#include "vtc_config.h"
#define VDMA_BASEADDR  XPAR_AXI_VDMA_0_BASEADDR

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 0x02000000
#define VIDEO_BASEADDR2 0x03000000

#define H_ACTIVE      1024
#define V_ACTIVE      600
#define H_STRIDE      1024
XIicPs   Iic;
u32 i=0;
#define SUM   2457600 //背景写黑  1280*720*4
void main()
{
              //设置内存中的背景
                            for(i=0;i<SUM;i++){
                                          Xil_Out16((VIDEO_BASEADDR0 + i), 0x00);
                                          Xil_Out16((VIDEO_BASEADDR1 + i), 0x00);
                                          Xil_Out16((VIDEO_BASEADDR2 + i), 0x00);
                            }
              // Initialize OV5640 regesiter

              I2C_config_init();
    // Config VTC
              Vtc_init(&Vtc, VTC_DEV_ID, &Vtc_timing, VIDEO_RESOLUTION_WSVGA);
              //Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0); // start address
              Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);  // start address
              Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);  // start address
              Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*3));                            // h offset (H_STRIDE* 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*3));                           // h size (H_ACTIVE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);                                   // v size (V_ACTIVE)
                            /*****************从DDR读数据设置**********************/
              Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B);                 // enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);               // start address
              Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);              // start address
              Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2);              // start address
              Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*3));                           // h offset (H_STRIDE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*3));                          // h size (H_ACTIVE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE);                                  // v size (V_ACTIVE)

              while (1) ;

}

640x480_1024x600 (使用缩放ip) 显示工程对应的main.c主函数


#include "I2C_16bit.h"
#include "xiicps.h"
#include "xil_io.h"
#include "xparameters.h"
#include "vtc_config.h"
#include "xhls_video_scaler_top.h"

#define XPAR_HLS_VIDEO_SCALER_TOP_DEVICE_ID   XPAR_HLS_VIDEO_SCALER_TOP_0_DEVICE_ID
#define VDMA_BASEADDR  XPAR_AXI_VDMA_0_BASEADDR

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 0x02000000
#define VIDEO_BASEADDR2 0x03000000

#define H_ACTIVE      1024
#define V_ACTIVE      600
#define H_STRIDE      1024

XHls_video_scaler_top   XHls_video_scaler;
XIicPs   Iic;

void XHls_video_scaler_initialize(void)
{
              int status;

              status=XHls_video_scaler_top_Initialize(&XHls_video_scaler, XPAR_HLS_VIDEO_SCALER_TOP_DEVICE_ID);
              if(0!=status)
              {
                            xil_printf("XPAR_HLS_VIDEO_SCALER FAILED\n");
              }
}

void XHls_video_scaler_setup(u16 row,u16 col,u16 drow,u16 dcol)
{
              XHls_video_scaler_top_SetRows(&XHls_video_scaler,row);
              XHls_video_scaler_top_SetCols(&XHls_video_scaler, col);
              XHls_video_scaler_top_SetDrows(&XHls_video_scaler, drow);
              XHls_video_scaler_top_SetDcols(&XHls_video_scaler, dcol);
              XHls_video_scaler_top_InterruptGlobalDisable(&XHls_video_scaler);
              XHls_video_scaler_top_EnableAutoRestart(&XHls_video_scaler);
              XHls_video_scaler_top_Start(&XHls_video_scaler);

}

void main()
{
              // Initialize OV5640 regesiter
              I2C_config_init();
// Config VTC
              Vtc_init(&Vtc, VTC_DEV_ID, &Vtc_timing, VIDEO_RESOLUTION_WSVGA);

              //Initialize XHls_video_scaler Ip
              XHls_video_scaler_initialize();
              //set input and output resolution ratio
              XHls_video_scaler_setup(480,640,600,1024);

              //Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0); // start address
              Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);  // start address
              Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);  // start address
              Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*3));                            // h offset (H_STRIDE* 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*3));                           // h size (H_ACTIVE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);                                   // v size (V_ACTIVE)
                            /*****************从DDR读数据设置**********************/
              Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B);                 // enable circular mode
              Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);               // start address
              Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);              // start address
              Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2);              // start address
              Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*3));                           // h offset (H_STRIDE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*3));                          // h size (H_ACTIVE * 3) bytes
              Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE);                                  // v size (V_ACTIVE)
              while (1) ;
}

1.3 测试验证

1.3.1 RGB接口LCD屏测试
(1)640X480分辨率输入,直接输出测试
可以看到图像显示仅占据一部分界面,这是因为输出分辨率大于输入分辨率。输入图像仅占据输出图像的一部分。
1)640x480分辨率输出
(2)640x480分辨率图像输入,采集图像经过HLS IP处理放大到1024x600输出。
2)1024x600分辨率输出

1.3.2 HDMI接口的LCD屏测试
(1)640X480分辨率输入,直接输出测试
可以看到图像显示仅占据一部分界面,这是因为输出分辨率大于输入分辨率。输入图像仅占据输出图像的一部分。
(2)640x480分辨率图像输入,采集图像经过HLS IP处理放大到1024x600输出。

2)1024x600分辨率输出
1.4 小结   

     实际使用中,屏的分辨率和使用方法各有差异,但是使用的思路是类似的,这里给出的是RGB、HDMI接口屏的OV5640传输显示,大家可以根据自己实际使用情况进行调整。

需要代码的朋友,可以给我留言,邮箱发送






发表评论已发布 21

子非鱼

发表于 2019-9-1 15:40:50 | 显示全部楼层

你好,代码能共享一下吗,我的邮箱是644920072@qq.com

lost_shadow

发表于 2019-9-3 15:33:44 | 显示全部楼层

求代码呀求代码zwdtju@163.com

Z8049

发表于 2019-11-6 19:39:04 | 显示全部楼层

可以发一份学习吗?万分感谢哈!邮箱:1573588074@qq.com

秦时明月

发表于 2020-2-26 12:16:34 | 显示全部楼层

你好,我这几天在调试ov640,想采集640*480p大小的图像,请问可以发我一份代码吗,我的邮箱是1805742433@qq.com,谢谢

I'mpossible

发表于 2020-4-1 16:22:51 | 显示全部楼层

感谢分享
回复

使用道具 举报

GALLAS

发表于 2020-6-20 15:57:08 | 显示全部楼层

可以发一份学习吗?非常非常非常非常非常感谢了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!邮箱:1830711937@qq.com

-m-、

发表于 2020-8-1 17:45:59 | 显示全部楼层

你好,可以发我一份工程吗? 非常感谢! 邮箱:374330795@qq.com

宛渠之民

发表于 2020-8-20 08:42:05 | 显示全部楼层

你好,求代码学习一个啊啊啊,邮箱1135118444@qq.com

回忆丶

发表于 2020-8-27 14:38:57 | 显示全部楼层

你好,希望能分享下代码,学习学习,谢谢!!   邮箱1373526704@qq.com
123下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则