搜索
bottom↓
回复: 1

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

[复制链接]

出0入234汤圆

发表于 2020-8-12 15:45:02 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2020-10-26 16:19 编辑

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)关注正点原子公众号,获取最新资料


160429lq4vawovapoakpkq.jpg

160428u3u53ddu5qwwpgx4 - 副本.png

第二十三章OV5640摄像头LCD显示



OV5640同OV7725一样,都是OmniVision(豪威科技)公司生产的CMOS图像传感器。不同的是,OV5640支持更高的分辨率、采集速率,具有更高的图像处理性能,主要应用在手机、数码相机、电脑多媒体等领域。本章我们将使用Zynq开发板实现对OV5640的数字图像采集并通过LCD实时显示。
本章包括以下几个部分:
22323.1OV5640简介
23.2实验任务
23.3硬件设计
23.4软件设计
23.5下载验证


23.1OV5640简介
OV5640是一款1/4英寸单芯片图像传感器,其感光阵列达到2592*1944(即500W像素),能实现最快15fps QSXVGA(2592*1944)或者90fps VGA(640*480)分辨率的图像采集。传感器采用OmniVision推出的OmniBSI(背面照度)技术,使传感器达到更高的性能,如高灵敏度、低串扰和低噪声。传感器内部集成了图像处理的功能,包括自动曝光控制(AEC)、自动白平衡(AWB)等。同时该传感器支持LED补光、MIPI(移动产业处理器接口)输出接口和DVP(数字视频并行)输出接口选择、ISP(图像信号处理)以及AFC(自动聚焦控制)等功能。
OV5640的功能框图如下图所示:
阿莫论坛发帖领航者专用1553.jpg

图 23.1.1 OV5640功能框图

由上图可知,时序发生器(timing generator)控制着感光阵列(image array)、放大器(AMP)、AD转换以及输出外部时序信号(VSYNC、HREF和PCLK),外部时钟XVCLK经过PLL锁相环后输出的时钟作为系统的控制时钟;感光阵列将光信号转化成模拟信号,经过增益放大器之后进入10位AD转换器;AD转换器将模拟信号转化成数字信号,并且经过ISP进行相关图像处理,最终输出所配置格式的10位视频数据流。增益放大器控制以及ISP等都可以通过寄存器(registers)来配置,配置寄存器的接口就是SCCB接口,该接口协议兼容IIC协议。
OV5640使用的是两线式SCCB接口总线,有关SCCB总线的详细介绍可以参考“OV7725摄像头LCD显示实验”中OV7725简介部分。虽然OV5640和OV7725都是采用SCCB接口总线来配置寄存器,但不同的是,OV7725是用8位(1个字节)来表示寄存器地址,而OV5640是用16位(两个字节)表示寄存器地址。
OV5640 SCCB的写传输协议如下图所示:
阿莫论坛发帖领航者专用11109.jpg

图 23.1.2 OV5640 SCCB写传输协议

上图中的ID ADDRESS是由7位器件地址和1位读写控制位构成(0:写 1:读),OV5640的器件地址为7’h3c,所以在写传输协议中,ID Address(W)= 8’h78(器件地址左移1位,低位补0);Sub-address(H)为高8位寄存器地址,Sub-address(L)为低8位寄存器地址,在OV5640众多寄存器中,有些寄存器是可改写的,有些是只读的,只有可改写的寄存器才能正确写入;Write Data为8位写数据,每一个寄存器地址对应8位的配置数据。
在OV5640正常工作之前,必须先对传感器进行初始化,即通过配置寄存器使其工作在预期的工作模式,以及得到较好画质的图像。因为SCCB的写传输协议和IIC几乎相同,因此我们可以直接使用IIC的驱动程序来配置摄像头。当然这么多寄存器也并非都需要配置,很多寄存器可以采用默认的值。OV公司提供了OV5640的软件应用手册(OV5640 Software Application Note,位于开发板所随附的资料“7_硬件资料/4_OV5640资料/OV5640_camera_module_software_application_notes.pdf”),如果某些寄存器不知道如何配置可以参考此手册,下表是本程序用到的关键寄存器的配置说明。
表 23.1.1 OV5640关键寄存器配置说明


2311.png


OV5640的寄存器较多,对于其它寄存器的描述可以参考OV5640的数据手册。需要注意的是,OV5640的数据手册并没有提供全部的寄存器描述,而大多数必要的寄存器配置在ov5640的软件应用手册中可以找到,可以结合这两个手册学习如何对OV5640进行配置。
输出图像参数设置
接下来,我们介绍一下OV5640的ISP输入窗口设置、预缩放窗口设置和输出大小窗口设置,这几个设置与我们的正常使用密切相关,有必要了解一下,它们的设置关系如下图所示:
阿莫论坛发帖领航者专用13502.jpg

图 23.1.3 图像窗口设置

ISP输入窗口设置(ISP Input Size)允许用户设置整个传感器显示区域(physical pixel size,2632*1951,其中2592*1944像素是有效的),开窗范围从0*0~2632*1951都可以任意设置。也就是上图中的X_ADDR_ST(寄存器地址0x3800、0x3801)、Y_ADDR_ST(寄存器地址0x3802、0x3803)、X_ADDR_END(寄存器地址0x3804、0x3805)和Y_ADDR_END(寄存器地址0x3806、0x3807)寄存器。该窗口设置范围中的像素数据将进入ISP进行图像处理。
预缩放窗口设置(pre-scaling size)允许用户在ISP输入窗口的基础上进行裁剪,用于设置将进行缩放的窗口大小,该设置仅在ISP输入窗口内进行X/Y方向的偏移。可以通过X_OFFSET(寄存器地址0x3810、0x3811)和Y_OFFSET(寄存器地址0x3812、0x3813)进行配置。
输出大小窗口设置(data output size)是在预缩放窗口的基础上,经过内部DSP进行缩放处理,并将处理后的数据输出给外部的图像窗口,图像窗口控制着最终的图像输出尺寸。可以通过X_OUTPUT_SIZE(寄存器地址0x3808、0x3809)和Y_OUTPUT_SIZE(寄存器地址0x380A、0x380B)进行配置。注意:当输出大小窗口与预缩放窗口比例不一致时,图像将进行缩放处理(图像变形),仅当两者比例一致时,输出比例才是1:1(正常图像)。
图 23.1.3中,右侧data output size区域,才是OV5640输出给外部的图像尺寸,也就是显示在显示器或者液晶屏上面的图像大小。输出大小窗口与预缩放窗口比例不一致时,会进行缩放处理,在显示器上面看到的图像将会变形。
输出像素格式
OV5640支持多种不同的数据像素格式,包括YUV(亮度参量和色度参量分开表示的像素格式)、RGB(其中RGB格式包含RGB565、RGB555等)以及RAW(原始图像数据),通过寄存器地址0x4300配置成不同的数据像素格式。
由于数据像素格式常用RGB565,我们这里也将ov5640配置为RGB565格式。由上表(表 23.1.1)可知,将寄存器0x4300寄存器的Bit[7:4]设置成0x6即可。OV5640支持调节RGB565输出格式中各颜色变量的顺序,对于我们常见的应用来说,一般是使用RGB或BGR序列。我们在“OV7725摄像头LCD显示实验”的章节中介绍过,OV7725摄像头按照RGB的顺序输出,本章我们将OV5640输出的RGB565的颜色顺序和OV7725保持一致,将寄存器0x4300寄存器的Bit[3:0]设置成0x1。因此,“OV7725摄像头LCD显示实验”章节中的图像采集模块可以直接用来采集OV5640输出的图像。
彩条测试模式
图像传感器配置成彩条测试模式后,会输出彩色的条纹,方便测试图像传感器是否正常工作,通过配置寄存器0x503d的Bit[7]位打开和关闭彩条模式。当需要打开彩条模式时,寄存器0x503d配置成0x80,关闭时配置成0x00,下图为打开彩条模式后图像输出的条纹。
阿莫论坛发帖领航者专用14957.jpg

图 23.1.4 彩条模式下的图像条纹

LED闪光灯
当外界环境光较暗时,传感器采集图像会受到较大影响,此时可以通过打开LED补光灯来弥补光照不足所带来的影响,就像手机在夜晚拍照时也会打开闪光灯来提高图像质量。通过配置寄存器0x3016=0x02,0x301c=0x02来使能LED补光灯功能;配置寄存器0x3019=0x02打开闪光灯,0x3019=0x00关闭闪光灯。
图像输出时序
接下来,我们介绍一下OV5640的图像数据输出时序,首先我们简单介绍一些定义。
QSXGA,这里指:分辨率为2592*1944的输出格式,类似的还有:QXGA(2048*1536)、UXGA(1600*1200)、SXGA(1280*1024)、WXGA(1440*900)、WXGA(1280*800)、XGA(1024*768)、SVGA(800*600)、VGA(640*480)、QVGA(320*240)和QQVGA(160*120)等。
PCLK:像素时钟,一个PCLK时钟输出一个像素或者半个像素(像素数据的高8位或者低8位)。
VSYNC:帧同步信号。
HREF/HSYNC:行同步信号。
D[9:0]:像素数据,在RGB565格式中,只有高8位是有效的。
tPclk:一个时钟周期 。
tp:一个像素点的周期,在RGB565和YUV422输出格式下,tp=2*tPclk;Raw输出格式下,tp=tPclk。
下图为OV5640输出图像数据的行时序图。
阿莫论坛发帖领航者专用15632.jpg

图 23.1.5 OV5640行时序图

从上图可以看出,传感器在HREF为高电平的时候输出图像数据,当HREF变高后,每一个 PCLK时钟,输出一个8位或者10位像素数据。比如我们采用QSXGA时序,RGB565格式输出,tp=2*tPclk,每2个字节组成一个像素的颜色,这样每行总共输出2592*2个PCLK,也就是2592*2个字节。
再来看看帧时序(QSXGA模式,分辨率2592*1944),如下图所示:
阿莫论坛发帖领航者专用15885.jpg

图 23.1.6 OV5640 QSXGA帧时序

由上图可知,VSYNC的上升沿作为一帧的开始,高电平同步脉冲的时间为5688tp,紧接着等待48276tp时间后,HREF开始拉高,此时输出有效数据;HREF由2592tp个高电平和252tp个低电平构成;最后一行图像数据输出完成之后等待14544tp时间,一帧数据传输结束。所以输出一帧图像的时间实际上是tFrame = 5596992tp。
从OV5640的行时序图和帧时序图可以发现,其输出时序和OV7725是非常相似的,只是时间参数不同而已,大家可以参考“OV7725摄像头LCD显示实验”中帧时序的介绍来学习OV5640的输出时序。
23.2实验任务
本节实验任务是使用领航者ZYNQ开发板及OV5640摄像头实现图像采集,并通过LCD实时显示。
23.3硬件设计
本次实验的硬件电路和“OV7725摄像头LCD显示实验”中的硬件电路是基本相同的,都使用了领航者Zynq开发板上的摄像头扩展接口,以及LCD接口,IO管脚位置的配置也是一样的。
唯一的不同点在于,原先在“OV7725摄像头LCD显示实验”中的Zynq输出给摄像头扩展接口的“cam_sgm_ctrl”信号,在本实验中变为了Zynq输出给OV5640的“电源休眠模式选择”信号cam_pwdn;且原来的cam_sgm_ctrl是我们需要一直赋值为高电平,但对于OV5640,cam_pwdn我们需要将其一直赋值为低电平,表示不休眠即正常工作模式。
OV5640摄像头的管脚分配如下表所示:
表 23.3.1 OV5640摄像头管脚分配

2331.png


在系统架构上,本次实验与“OV7725摄像头LCD显示实验”也是类似的,只是用于采集摄像头数据的摄像头采集IP核稍微不同,即上文提到的一个管脚功能和赋值的不同。本次实验的系统架构如下图所示:
阿莫论坛发帖领航者专用17263.jpg

图 23.3.1 系统架构框图

有关整个系统架构的搭建过程,请读者参考OV7725摄像头LCD显示实验。连线后的设计画布如下图所示:
阿莫论坛发帖领航者专用17350.jpg

图 23.3.3 IP Integrator设计画布

其中,OV5640图像采集模块如下图所示:
阿莫论坛发帖领航者专用17419.jpg

图 23.3.2 OV5640图像采集模块

ov5640_capture_data IP核的源代码与“OV7725摄像头LCD显示实验”中的ov7725_capture_data IP核的代码基本是一样的,唯一的不同点在于cam_pwdn信号的赋值,如下所示:
  1. 1    module  ov5640_capture_data(
  2. 2        input                 rst_n           ,  //复位信号
  3. 3   
  4. 4       //摄像头接口
  5. 与OV7725摄像头LCD显示实验相同的代码部分被省略。。。。。。
  6. 9        output                cam_rst_n       ,  //cmos 复位信号,低电平有效
  7. 10       output                cam_pwdn        ,  //电源休眠模式选择
  8. 与OV7725摄像头LCD显示实验相同的代码部分被省略。。。。。。
  9. 50
  10. 51   //不对摄像头硬件复位,固定高电平
  11. 52   assign  cam_rst_n = 1'b1;
  12. 53   
  13. 54   //电源休眠模式选择 0:正常模式 1:电源休眠模式
  14. 55   assign  cam_pwdn  = 1'b0;
  15. 56   
  16. 与OV7725摄像头LCD显示实验相同的代码部分被省略。。。。。。
  17. 141  
  18. 142  endmodule
复制代码

为工程添加约束文件,约束文件如下:
  1. #----------------------摄像头接口的时钟---------------------------
  2. #72M
  3. create_clock -period 13.888 -name cam_pclk [get_ports cam_pclk]
  4. set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets cam_pclk_IBUF]

  5. #----------------------LCD接口---------------------------
  6. set_property -dict {PACKAGE_PIN Y18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[0]}]
  7. set_property -dict {PACKAGE_PIN Y19 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[1]}]
  8. set_property -dict {PACKAGE_PIN W20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[2]}]
  9. set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[3]}]
  10. set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[4]}]
  11. set_property -dict {PACKAGE_PIN U15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[5]}]
  12. set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[6]}]
  13. set_property -dict {PACKAGE_PIN U20 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[7]}]
  14. set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[8]}]
  15. set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[9]}]
  16. set_property -dict {PACKAGE_PIN N15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[10]}]
  17. set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[11]}]
  18. set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[12]}]
  19. set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[13]}]
  20. set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[14]}]
  21. set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[15]}]
  22. set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[16]}]
  23. set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[17]}]
  24. set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[18]}]
  25. set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[19]}]
  26. set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[20]}]
  27. set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[21]}]
  28. set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[22]}]
  29. set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb_tri_io[23]}]
  30. set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports lcd_hs]
  31. set_property -dict {PACKAGE_PIN P20 IOSTANDARD LVCMOS33} [get_ports lcd_vs]
  32. set_property -dict {PACKAGE_PIN N20 IOSTANDARD LVCMOS33} [get_ports lcd_de]
  33. set_property -dict {PACKAGE_PIN Y16 IOSTANDARD LVCMOS33} [get_ports lcd_bl]
  34. set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports lcd_clk]

  35. #----------------------摄像头接口---------------------------
  36. set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports cam_rst_n]
  37. set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports cam_pwdn]
  38. set_property -dict {PACKAGE_PIN P16 IOSTANDARD LVCMOS33} [get_ports {cam_data[0]}]
  39. set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {cam_data[1]}]
  40. set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {cam_data[2]}]
  41. set_property -dict {PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports {cam_data[3]}]
  42. set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {cam_data[4]}]
  43. set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {cam_data[5]}]
  44. set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {cam_data[6]}]
  45. set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {cam_data[7]}]
  46. set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS33} [get_ports cam_href]
  47. set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports cam_pclk]
  48. set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports cam_vsync]
  49. #cam_scl:
  50. set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {emio_sccb_tri_io[0]}]
  51. #cam_sda:
  52. set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {emio_sccb_tri_io[1]}]

  53. set_property PULLUP true [get_ports {emio_sccb_tri_io[1]}]
复制代码

最后在左侧Flow Navigator导航栏中找到PROGRAM AND DEBUG,点击该选项中的“ Generate Bitstream”,对设计进行综合、实现、并生成Bitstream文件。
在生成Bitstream之后,在菜单栏中选择 File > Export > Export hardware导出硬件,并在弹出的对话框中,勾选“Include bitstream”。然后在菜单栏选择File > Launch SDK,启动SDK软件。
23.4软件设计
打开SDK后,我们创建一个Application Project,添加到工程中的源文件与“OV7725摄像头LCD显示实验”基本类似,不同之处在于,ov5640文件夹下存放用于初始化ov5640的源代码。如下图所示:
阿莫论坛发帖领航者专用112581.jpg

图 23.4.1 SDK工程的源文件

main函数的代码如下所示:
  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 "xgpio.h"
  8. 8    #include "xaxivdma.h"
  9. 9    #include "xaxivdma_i.h"
  10. 10   #include "display_ctrl/display_ctrl.h"
  11. 11   #include "vdma_api/vdma_api.h"
  12. 12   #include "emio_sccb_cfg/emio_sccb_cfg.h"
  13. 13   #include "ov5640/ov5640_init.h"
  14. 14   
  15. 15   //宏定义
  16. 16   #define BYTES_PIXEL        3                           //像素字节数,RGB888占3个字节
  17. 17   #define FRAME_BUFFER_NUM   3                           //帧缓存个数3
  18. 18   #define DYNCLK_BASEADDR    XPAR_AXI_DYNCLK_0_BASEADDR  //动态时钟基地址
  19. 19   #define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID    //VDMA器件ID
  20. 20   #define DISP_VTC_ID        XPAR_VTC_0_DEVICE_ID        //VTC器件ID
  21. 21   //PL端  AXI GPIO 0(lcd_id)器件 ID
  22. 22   #define AXI_GPIO_0_ID      XPAR_AXI_GPIO_0_DEVICE_ID   
  23. 23   //使用AXI GPIO(lcd_id)通道1
  24. 24   #define AXI_GPIO_0_CHANEL  1                           
  25. 25   
  26. 26   //全局变量
  27. 27   //frame buffer的起始地址
  28. 28   unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR
  29. 29                                          + 0x1000000);
  30. 30   XAxiVdma     vdma;
  31. 31   DisplayCtrl  dispCtrl;
  32. 32   XGpio        axi_gpio_inst;   //PL端 AXI GPIO 驱动实例
  33. 33   VideoMode    vd_mode;
  34. 34   unsigned int lcd_id;
  35. 35   
  36. 36   int main(void)
  37. 37   {
  38. 38      u32 status;
  39. 39      u16 cmos_h_pixel;   //ov5640 DVP 输出水平像素点数
  40. 40      u16 cmos_v_pixel;   //ov5640 DVP 输出垂直像素点数
  41. 41      u16 total_h_pixel;  //ov5640 水平总像素大小
  42. 42      u16 total_v_pixel;  //ov5640 垂直总像素大小
  43. 43   
  44. 44      //获取LCD的ID
  45. 45      XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_0_ID);
  46. 46      lcd_id = LTDC_PanelID_Read(&axi_gpio_inst,AXI_GPIO_0_CHANEL);
  47. 47      xil_printf("lcd_id = %x\n\r",lcd_id);
  48. 48   
  49. 49      //根据获取的LCD的ID号来进行ov5640显示分辨率参数的选择
  50. 50      switch(lcd_id){
  51. 51          case 0x4342 :
  52. 52              cmos_h_pixel = 480;
  53. 53              cmos_v_pixel = 272;
  54. 54              total_h_pixel = 1800;
  55. 55              total_v_pixel = 1000;
  56. 56              break;
  57. 57          case 0x7084 :
  58. 58              cmos_h_pixel = 800;
  59. 59              cmos_v_pixel = 480;
  60. 60              total_h_pixel = 1800;
  61. 61              total_v_pixel = 1000;
  62. 62              break;
  63. 63          case 0x7016 :
  64. 64              cmos_h_pixel = 1024;
  65. 65              cmos_v_pixel = 600;
  66. 66              total_h_pixel = 2200;
  67. 67              total_v_pixel = 1000;
  68. 68              break;
  69. 69          case 0x1018 :
  70. 70              cmos_h_pixel = 1280;
  71. 71              cmos_v_pixel = 800;
  72. 72              total_h_pixel = 2570;
  73. 73              total_v_pixel = 980;
  74. 74              break;
  75. 75          default :
  76. 76              cmos_h_pixel = 480;
  77. 77              cmos_v_pixel = 272;
  78. 78              total_h_pixel = 1800;
  79. 79              total_v_pixel = 1000;
  80. 80              break;
  81. 81      }
  82. 82   
  83. 83      emio_init();                         //初始化EMIO
  84. 84      status = ov5640_init( cmos_h_pixel,  //初始化ov5640
  85. 85                            cmos_v_pixel,
  86. 86                           total_h_pixel,
  87. 87                           total_v_pixel);
  88. 88      if(status == 0)
  89. 89          xil_printf("OV5640 detected successful!\r\n");
  90. 90      else
  91. 91          xil_printf("OV5640 detected failed!\r\n");
  92. 92   
  93. 93      //根据获取的LCD的ID号来进行video参数的选择
  94. 94      switch(lcd_id){
  95. 95          case 0x4342 : vd_mode = VMODE_480x272;  break;
  96. 96          case 0x7084 : vd_mode = VMODE_800x480;  break;
  97. 97          case 0x7016 : vd_mode = VMODE_1024x600; break;
  98. 98          case 0x1018 : vd_mode = VMODE_1280x800; break;
  99. 99          default : vd_mode = VMODE_800x480; break;
  100. 100     }
  101. 101  
  102. 102     //配置VDMA
  103. 103     run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
  104. 104                             frame_buffer_addr,0,0,BOTH);
  105. 105     //初始化Display controller
  106. 106     DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
  107. 107     //设置VideoMode
  108. 108     DisplaySetMode(&dispCtrl, &vd_mode);
  109. 109     DisplayStart(&dispCtrl);
  110. 110  
  111. 111      return 0;
  112. 112  }
复制代码

main()函数的整体流程架构与“OV7725摄像头LCD显示实验”基本类似。但是,由于ov5640不像ov7725那样只能输出固定分辨率的视频图像,ov5640能够对输出图像的分辨率大小进行调整,所以我们可以根据具有不同分辨率的LCD来使ov5640输出不同分辨率的视频图像。代码中的第39-42行定义了4个变量,用于存储ov5640的分辨率配置参数。代码中第50行的switch语句,根据读取到的LCD的ID号来对ov5640的分辨率配置参数进行赋值,然后这些变量值将作为实参来传递给ov5640_init()函数。
ov5640的初始化过程完成之后,就是对VDMA、VTC以及动态时钟配置的初始化,如代码中的第93-114 行所述。
ov5640_init()函数的代码如下所示:
  1. 1    u8 ov5640_init( u16 cmos_h_pixel,  u16 cmos_v_pixel,  
  2. 2                   u16 total_h_pixel,  u16 total_v_pixel )
  3. 3    {
  4. 4       u16 cam_id = 0;
  5. 5      
  6. 6       usleep(20000);                            //OV5640上电到开始配置sccb至少等待20ms
  7. 7   
  8. 8        //读OV5640摄像头ID
  9. 9        cam_id  = sccb_read_reg16(0x300b);       //LSB  0x40
  10. 10       cam_id |= sccb_read_reg16(0x300a) << 8;  //MSB  0x56
  11. 11      
  12. 12       if(cam_id != 0x5640)                     //获取到正确的OV5640 ID
  13. 13           return 1;
  14. 14       else{
  15. 15          //先对寄存器进行软件复位,使寄存器恢复初始值
  16. 16          //寄存器软件复位后,需要延时1ms才能配置其它寄存器
  17. 17          sccb_write_reg16(0x3008,0x82); //Bit[7]:复位 Bit[6]:电源休眠
  18. 18   
  19. 19          //延时1ms
  20. 20          usleep(1000);
  21. 21   
  22. 22          sccb_write_reg16(0x3008,0x02); //正常工作模式
  23. 配置代码较长,省略部分源代码……
  24. 250         //设置输出像素个数
  25. 251         sccb_write_reg16(0x3808, cmos_h_pixel >> 8     );  //DVP 输出水平像素点数高4位
  26. 252         sccb_write_reg16(0x3809, cmos_h_pixel &  0x00FF);  //DVP输出水平像素点数低8位
  27. 253         sccb_write_reg16(0x380a, cmos_v_pixel >> 8     );  //DVP输出垂直像素点数高3位
  28. 254         sccb_write_reg16(0x380b, cmos_v_pixel &  0x00FF);  //DVP输出垂直像素点数低8位
  29. 255         sccb_write_reg16(0x380c, total_h_pixel >> 8    );  //水平总像素大小高5位
  30. 256         sccb_write_reg16(0x380d, total_h_pixel & 0x00FF);  //水平总像素大小低8位
  31. 257         sccb_write_reg16(0x380e, total_v_pixel >> 8    );  //垂直总像素大小高5位
  32. 258         sccb_write_reg16(0x380f, total_v_pixel & 0x00FF);  //垂直总像素大小低8位      
  33. 配置代码较长,省略部分源代码……
  34. 283         return 0;
  35. 284     }
  36. 285  }
复制代码

代码中的第9-10行读取寄存器地址0x300B和0x300A来获取OV5640摄像头的ID,注意OV7725摄像头的ID为“0x5640”。如果获取的ID不等于0x5640,则返回1;否则开始对OV7725摄像头进行配置。第250-258行将在main函数中赋值的分辨率配置数据写入到0x5640中,配置完成后函数返回0。
23.5下载验证
编译完工程之后我们就可以开始下载程序了。将OV5640摄像头模块插在领航者Zynq开发板的“OLED/CAMERA”插座上,并将LCD的排线接头插入开发板上的LCD接线座。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。
在SDK软件下方的SDK Terminal窗口中点击右上角的加号设置并连接串口。然后下载本次实验硬件设计过程中所生成的BIT文件,来对PL进行配置。最后下载软件程序,下载完成后,在下方的SDK Terminal中可以看到应用程序打印的信息,如下图所示:
阿莫论坛发帖领航者专用118860.jpg

图 23.5.1 串口打印的信息

同时,RGB LCD液晶屏上显示出OV5640摄像头采集的图像,说明本次OV5640摄像头RGB LCD屏显示的实验在领航者ZYQN开发板上验证成功,如下图所示:
阿莫论坛发帖领航者专用118979.jpg

图 23.5.2 RGB LCD屏显示图像数据


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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出16170入6148汤圆

发表于 2020-8-21 13:39:08 来自手机 | 显示全部楼层
打赏!

庆祝论坛“打赏”功能实施, 现在开始发技术主题,可以获得打赏
https://www.amobbs.com/thread-5735948-1-1.html
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-27 06:06

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

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