【正点原子FPGA连载】第四十二章OV5640摄像头HDMI显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

1)实验平台:正点原子新起点V2开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113
2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html
3)对正点原子FPGA感兴趣的同学可以加群讨论:994244016
4)关注正点原子公众号,获取最新资料更新
在这里插入图片描述

第四十二章OV5640摄像头HDMI显示实验

LCD屏上实时显示出了摄像头采集的图像。本章将使用FPGA开发板实现对OV5640的数字图像采集并在HDMI显示器上实时显示。
本章包括以下几个部分:
4141.1简介
41.2实验任务
41.3硬件设计
41.4程序设计
41.5下载验证

42.1简介

在“OV5640摄像头RGB-LCD显示实验”中对OV5640的视频传输时序、SCCB协议以及寄存器的配置信息等内容作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“OV5640摄像头RGB-LCD显示实验”中的OV5640简介部分。
42.2实验任务
本节实验任务是使用新起点开发板及OV5640摄像头实现图像采集,并通过HDMI接口驱动HDMI显示器,并实时显示出图像。
42.3硬件设计
摄像头扩展接口原理图及OV5640模块说明与“OV5640摄像头RGB-LCD显示实验”完全相同,请参考“OV5640摄像头RGB-LCD显示实验”硬件设计部分。HDMI接口部分的硬件设计请参考“HDMI彩条显示实验”中的硬件设计部分。
由于OV5640、HDMI接口和SDRAM引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里不再列出管脚分配。
42.4程序设计
根据实验任务,首先我们设计如图 42.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头RGB-LCD显示实验”的整体架构。本次实验包括以下模块:时钟模块、IIC配置模块、IIC驱动模块、SDRAM控制器模块、摄像头图像采集模块和HDMI顶层模块。其中IIC配置模块、IIC驱动模块、摄像头图像采集模块和SDRAM控制器模块我们没有做任何修改,这些模块在“OV5640摄像头RGB-LCD显示实验”中已经说明过,这里不再详述,本次实验将LCD顶层模块替换成了HDMI顶层模块。因为本次实验用的是HDMI显示器来显示,所以需要将LCD顶层模块替换成HDMI顶层模块。本次实验也不需要图像尺寸配置模块,因为本次实验摄像头的分辨率是固定的,其分辨率为1280x800。
OV5640摄像头HDMI显示系统框图如下图所示:
在这里插入图片描述

图 42.4.1 顶层系统框图
由上图可知,本节实验有两个锁相环,其中pll_clk锁相环为IIC配置模块和SDRAM模块提供时钟信号,而clk_hdmi锁相环则是专门为HDMI控制模块提供时钟,本节实验采用的是1280*800的分辨率,因此clk_hdmi锁相环提供的像素时钟就是71Mhz(VESA标准)和355Mhz(并行转串行5倍时钟)。其他的模块像SDRAM控制器模块,HDMI控制器模块等等都在前面的实验中做过详细的讲解了,因此本节实验就不再重复讲解了,下面给出本节实验的顶层代码:

1   module ov5640_hdmi(    
2       input         sys_clk    ,  //系统时钟
3       input         sys_rst_n  ,  //系统复位,低电平有效
4       //摄像头 
5       input         cam_pclk   ,  //cmos 数据像素时钟
6       input         cam_vsync  ,  //cmos 场同步信号
7       input         cam_href   ,  //cmos 行同步信号
8       input  [7:0]  cam_data   ,  //cmos 数据  
9       output        cam_rst_n  ,  //cmos 复位信号,低电平有效
10      output        cam_pwdn   ,  //cmos 电源休眠模式选择信号
11      output        cam_scl    ,  //cmos SCCB_SCL线
12      inout         cam_sda    ,  //cmos SCCB_SDA线
13      //SDRAM 
14      output        sdram_clk  ,  //SDRAM 时钟
15      output        sdram_cke  ,  //SDRAM 时钟有效
16      output        sdram_cs_n ,  //SDRAM 片选
17      output        sdram_ras_n,  //SDRAM 行有效
18      output        sdram_cas_n,  //SDRAM 列有效
19      output        sdram_we_n ,  //SDRAM 写有效
20      output [1:0]  sdram_ba   ,  //SDRAM Bank地址
21      output [1:0]  sdram_dqm  ,  //SDRAM 数据掩码
22      output [12:0] sdram_addr ,  //SDRAM 地址
23      inout  [15:0] sdram_data ,  //SDRAM 数据    
24      //HDMI接口
25      output       tmds_clk_p,    // TMDS 时钟通道
26      output       tmds_clk_n,
27      output [2:0] tmds_data_p,   // TMDS 数据通道
28      output [2:0] tmds_data_n
29      );
30  
31  //parameter define
32  parameter SLAVE_ADDR    = 7'h3c          ; //OV5640的器件地址7'h3c
33  parameter BIT_CTRL      = 1'b1           ; //OV5640的字节地址为16位  0:8位 1:16位
34  parameter CLK_FREQ      = 27'd50_000_000 ; //i2c_dri模块的驱动时钟频率 
35  parameter I2C_FREQ      = 18'd250_000    ; //I2C的SCL时钟频率,不超过400KHz
36  parameter V_CMOS_DISP   = 11'd800        ; //CMOS分辨率--行
37  parameter H_CMOS_DISP   = 11'd1280       ; //CMOS分辨率--列 
38  parameter TOTAL_H_PIXEL = 13'd2570       ; //CMOS分辨率--行
39  parameter TOTAL_V_PIXEL = 13'd980        ;
40  
41  //wire define
42  wire        clk_100m       ;  //100mhz时钟,SDRAM操作时钟
43  wire        clk_100m_shift ;  //100mhz时钟,SDRAM相位偏移时钟
44  wire        clk_50m        ;
45  wire        hdmi_clk       ;  
46  wire        hdmi_clk_5     ;  
47  wire        locked         ;
48  wire        locked_hdmi    ;
49  wire        rst_n          ;
50  wire        sys_init_done  ;  //系统初始化完成(sdram初始化+摄像头初始化)
51  
52  wire        i2c_exec       ;  //I2C触发执行信号
53  wire [23:0] i2c_data       ;  //I2C要配置的地址与数据(高8位地址,低8位数据)          
54  wire        i2c_done       ;  //I2C寄存器配置完成信号
55  wire        i2c_dri_clk    ;  //I2C操作时钟
56  wire [ 7:0] i2c_data_r     ;  //I2C读出的数据
57  wire        i2c_rh_wl      ;  //I2C读写控制信号
58  wire        cam_init_done  ;  //摄像头初始化完成
59                          
60  wire        wr_en          ;  //sdram_ctrl模块写使能
61  wire [15:0] wr_data        ;  //sdram_ctrl模块写数据
62  wire        rd_en          ;  //sdram_ctrl模块读使能
63  wire [15:0] rd_data        ;  //sdram_ctrl模块读数据
64  wire        sdram_init_done;  //SDRAM初始化完成
65  
66  //*****************************************************
67  //**                    main code
68  //*****************************************************
69  
70  assign  rst_n = sys_rst_n & locked & locked_hdmi;
71  //系统初始化完成:SDRAM和摄像头都初始化完成
72  //避免了在SDRAM初始化过程中向里面写入数据
73  assign  sys_init_done = sdram_init_done & cam_init_done;
74  //电源休眠模式选择 0:正常模式 1:电源休眠模式
75  assign  cam_pwdn  = 1'b0;
76  assign  cam_rst_n = 1'b1;
77  
78  //锁相环
79  pll u_pll(
80      .areset             (~sys_rst_n),
81      .inclk0             (sys_clk),            
82      .c0                 (clk_100m),
83      .c1                 (clk_100m_shift), 
84      .c2                 (clk_50m), 
85      .locked             (locked)
86      );
87  
88  pll_hdmi    pll_hdmi_inst (
89      .areset             ( ~sys_rst_n  ),
90      .inclk0             ( sys_clk     ),
91      .c0                 ( hdmi_clk    ),//hdmi pixel clock 71Mhz
92      .c1                 ( hdmi_clk_5  ),//hdmi pixel clock*5 355Mhz
93      .locked             ( locked_hdmi )
94      );
95      
96  //I2C配置模块
97  i2c_ov5640_rgb565_cfg u_i2c_cfg(
98      .clk                (i2c_dri_clk),
99      .rst_n              (rst_n      ),
100             
101     .i2c_exec           (i2c_exec   ),
102     .i2c_data           (i2c_data   ),
103     .i2c_rh_wl          (i2c_rh_wl  ),      //I2C读写控制信号
104     .i2c_done           (i2c_done   ), 
105     .i2c_data_r         (i2c_data_r ),   
106                 
107     .cmos_h_pixel       (H_CMOS_DISP  ),    //CMOS水平方向像素个数
108     .cmos_v_pixel       (V_CMOS_DISP  ),    //CMOS垂直方向像素个数
109     .total_h_pixel      (TOTAL_H_PIXEL),    //水平总像素大小
110     .total_v_pixel      (TOTAL_V_PIXEL),    //垂直总像素大小
111         
112     .init_done          (cam_init_done) 
113     );    
114 
115 //I2C驱动模块
116 i2c_dri #(
117     .SLAVE_ADDR         (SLAVE_ADDR    ),    //参数传递
118     .CLK_FREQ           (CLK_FREQ      ),              
119     .I2C_FREQ           (I2C_FREQ      ) 
120     )
121 u_i2c_dr(
122     .clk                (clk_50m       ),
123     .rst_n              (rst_n         ),
124 
125     .i2c_exec           (i2c_exec      ),   
126     .bit_ctrl           (BIT_CTRL      ),   
127     .i2c_rh_wl          (i2c_rh_wl     ),     //固定为0,只用到了IIC驱动的写操作   
128     .i2c_addr           (i2c_data[23:8]),   
129     .i2c_data_w         (i2c_data[7:0] ),   
130     .i2c_data_r         (i2c_data_r    ),   
131     .i2c_done           (i2c_done      ),    
132     .scl                (cam_scl       ),   
133     .sda                (cam_sda       ),
134     .dri_clk            (i2c_dri_clk   )       //I2C操作时钟
135     );
136 
137 //CMOS图像数据采集模块
138 cmos_capture_data u_cmos_capture_data(         //系统初始化完成之后再开始采集数据 
139     .rst_n              (rst_n & sys_init_done),
140     
141     .cam_pclk           (cam_pclk ),
142     .cam_vsync          (cam_vsync),
143     .cam_href           (cam_href ),
144     .cam_data           (cam_data ),         
145     
146     .cmos_frame_vsync   (),
147     .cmos_frame_href    (),
148     .cmos_frame_valid   (wr_en    ),      //数据有效使能信号
149     .cmos_frame_data    (wr_data  )       //有效数据 
150     );
151 
152 
153 //SDRAM 控制器顶层模块,封装成FIFO接口
154 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}
155 sdram_top u_sdram_top(
156     .ref_clk            (clk_100m),         //sdram 控制器参考时钟
157     .out_clk            (clk_100m_shift),   //用于输出的相位偏移时钟
158     .rst_n              (rst_n),            //系统复位
159                                             
160     //用户写端口                              
161     .wr_clk             (cam_pclk),         //写端口FIFO: 写时钟
162     .wr_en              (wr_en),            //写端口FIFO: 写使能
163     .wr_data            (wr_data),          //写端口FIFO: 写数据
164     .wr_min_addr        (24'd0),            //写SDRAM的起始地址
165     .wr_max_addr        (V_CMOS_DISP*H_CMOS_DISP-1),   //写SDRAM的结束地址
166     .wr_len             (10'd512),          //写SDRAM时的数据突发长度
167     .wr_load            (~rst_n),           //写端口复位: 复位写地址,清空写FIFO
168                                             
169     //用户读端口                              
170     .rd_clk             (hdmi_clk),          //读端口FIFO: 读时钟
171     .rd_en              (rd_en),            //读端口FIFO: 读使能
172     .rd_data            (rd_data),          //读端口FIFO: 读数据
173     .rd_min_addr        (24'd0),            //读SDRAM的起始地址
174     .rd_max_addr        (V_CMOS_DISP*H_CMOS_DISP-1),   //读SDRAM的结束地址
175     .rd_len             (10'd512),          //从SDRAM中读数据时的突发长度
176     .rd_load            (~rst_n),           //读端口复位: 复位读地址,清空读FIFO
177                                                 
178     //用户控制端口                                
179     .sdram_read_valid   (1'b1),             //SDRAM 读使能
180     .sdram_pingpang_en  (1'b1),             //SDRAM 乒乓操作使能
181     .sdram_init_done    (sdram_init_done),  //SDRAM 初始化完成标志
182                                             
183     //SDRAM 芯片接口                                
184     .sdram_clk          (sdram_clk),        //SDRAM 芯片时钟
185     .sdram_cke          (sdram_cke),        //SDRAM 时钟有效
186     .sdram_cs_n         (sdram_cs_n),       //SDRAM 片选
187     .sdram_ras_n        (sdram_ras_n),      //SDRAM 行有效
188     .sdram_cas_n        (sdram_cas_n),      //SDRAM 列有效
189     .sdram_we_n         (sdram_we_n),       //SDRAM 写有效
190     .sdram_ba           (sdram_ba),         //SDRAM Bank地址
191     .sdram_addr         (sdram_addr),       //SDRAM 行/列地址
192     .sdram_data         (sdram_data),       //SDRAM 数据
193     .sdram_dqm          (sdram_dqm)         //SDRAM 数据掩码
194     );
195 
196 //例化HDMI顶层模块
197 hdmi_top u_hdmi_top(
198     .hdmi_clk       (hdmi_clk   ),
199     .hdmi_clk_5     (hdmi_clk_5 ),
200     .rst_n          (rst_n      ),
201                 
202     .rd_data        (rd_data    ),
203     .rd_en          (rd_en      ), 
204     .h_disp         (),  
205     .v_disp         (),
206     .pixel_xpos     (),
207     .pixel_ypos     (),
208     .video_vs       (),  
209     .tmds_clk_p     (tmds_clk_p ),
210     .tmds_clk_n     (tmds_clk_n ),
211     .tmds_data_p    (tmds_data_p),
212     .tmds_data_n    (tmds_data_n)
213     );   
214 
215 endmodule 

FPGA顶层模块(ov5640_hdmi)例化了以下六个模块:时钟模块、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov5640_rgb565_cfg)、摄像头图像采集模块(cmos_capture_data)、SDRAM读写控制模块(sdram_top)和HDMI顶层模块(hdmi_top)。
时钟模块:时钟模块通过调用PLL IP核实现,共输出5个时钟,频率分别为100M时钟、100M偏移-75度时钟、50M时钟、71Mhz时钟和355M时钟(HDMI像素时钟的5倍频)。其中pll 产生了50M时钟、100M时钟和100M偏移-75度时钟,pll_hdmi 产生了71Mhz时钟和355M时钟,这里之所以用两个锁相环是因为HDMI所用的时钟71Mhz与SDRAM控制模块使用的100M时钟不是整数倍,使用一个锁相环不符合设计要求。100Mhz时钟作为SDRAM控制模块的驱动时钟,100M偏移-75度时钟用来输出给外部SDRAM芯片使用,50Mhz时钟作为I2C驱动模块的驱动时钟,71Mhz时钟和355M时钟(HDMI像素时钟的5倍频)负责驱动HDMI顶层模块。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV5640 SCCB接口总线,用户可根据该模块提供的用户接口对OV5640的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
I2C配置模块(i2c_ov5640_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV5640的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对OV5640传感器的初始化。OV7725和OV5640寄存器配置时序非常相似,有关该模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
摄像头图像采集模块(cmos_capture_data):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成SDRAM读写控制模块的写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。OV7725和OV5640图像输出时序非常相似,有关该模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
SDRAM读写控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存图像传感器输出的图像数据。该模块将SDRAM复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节,修改部分请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供显示器参数、场同步信号和数据请求信号。关HDMI顶层模块的详细介绍请大家参考“OV5640摄像头HDMI显示实验”章节。
42.5下载验证
编译完工程之后我们就可以开始下载程序。将OV5640摄像头模块插在新起点开发板“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,验证OV5640 HDMI实时显示功能。下载完成后观察HDMI显示器显示的图案如下图所示,说明OV5640 HDMI实时显示程序下载验证成功。

在这里插入图片描述

图 42.5.1 HDMI实时显示图像

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值