OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9442|回复: 0
打印 上一主题 下一主题

[XILINX] 【正点原子FPGA连载】第三十九章OV5640摄像头HDMI显示实验--摘自【正点原子】超越者之FPGA开发指南

[复制链接]

1212

主题

1226

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
5221
金钱
5221
注册时间
2019-5-8
在线时间
1316 小时
跳转到指定楼层
楼主
发表于 2021-1-22 17:15:48 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

1)实验平台:正点原子超越者FPGA开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=631660290421
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz-chaoyuezhe.html
4)本章实例源码下载: 32_ov5640_hdmi.rar (6.44 MB, 下载次数: 27)


5)正点原子FPGA交流群:
905624739点击加入:
6)关注正点原子公众号,获取最新资料更新




第三十九章OV5640摄像头HDMI显示实验


在OV5640摄像头RGB-LCD显示实验中,成功地在LCD屏上实时显示出了摄像头采集的图像。本章将使用FPGA开发板实现对OV5640的数字图像采集并在HDMI显示器上实时显示。
本章包括以下几个部分:
3939.1  简介
39.2  实验任务
39.3  硬件设计
39.4  程序设计
39.5  下载验证


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

图 39.4.1 顶层系统框图

由上图可知,时钟模块(clock)为HDMI顶层模块、DDR控制模块以及摄像头驱动模块提供驱动时钟。摄像头驱动模块控制着传感器初始化的开始与结束。传感器初始化完成后图像采集模块将采集到的数据写入DDR控制模块,HDMI顶层模块从DDR控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
顶层模块的代码如下:
  1. 1   module ov5640_hdmi(   
  2. 2       input                 sys_clk,        //系统时钟
  3. 3       input                 sys_rst_n,      //系统复位,低电平有效
  4. 4       //摄像头接口                          
  5. 5       input                 cam_pclk,       //cmos 数据像素时钟
  6. 6       input                 cam_vsync,      //cmos 场同步信号
  7. 7       input                 cam_href,       //cmos 行同步信号
  8. 8       input   [7:0]         cam_data,       //cmos 数据
  9. 9       output                cam_rst_n,      //cmos 复位信号,低电平有效
  10. 10      output                cam_pwdn ,      //电源休眠模式选择 0:正常模式 1:电源休眠模式
  11. 11      output                cam_scl,        //cmos SCCB_SCL线
  12. 12      inout                 cam_sda,        //cmos SCCB_SDA线      
  13. 13    //ddr3 port
  14. 14      inout   [15:0]        mcb3_dram_dq,     
  15. 15      output  [13:0]        mcb3_dram_a,      
  16. 16      output  [2:0]         mcb3_dram_ba,     
  17. 17      output                mcb3_dram_ras_n,  
  18. 18      output                mcb3_dram_cas_n,   
  19. 19      output                mcb3_dram_we_n,   
  20. 20      output                mcb3_dram_reset_n,
  21. 21      output                mcb3_dram_cke,   
  22. 22      output                mcb3_dram_dm,     
  23. 23      inout                 mcb3_dram_udqs,   
  24. 24      inout                 mcb3_dram_udqs_n,
  25. 25      inout                 mcb3_rzq,         
  26. 26      inout                 mcb3_zio,         
  27. 27      output                mcb3_dram_udm,   
  28. 28      inout                 mcb3_dram_dqs,   
  29. 29      inout                 mcb3_dram_dqs_n,  
  30. 30      output                mcb3_dram_ck,     
  31. 31      output                mcb3_dram_ck_n,      
  32. 32  
  33. 33      output                init_calib_complete,   
  34. 34      //hdmi接口                              
  35. 35      output                tmds_clk_p,         // TMDS 时钟通道
  36. 36      output                tmds_clk_n,
  37. 37      output  [2:0]         tmds_data_p,        // TMDS 数据通道
  38. 38      output  [2:0]         tmds_data_n  
  39. 39      );
  40. 40  
  41. 41  //parameter define
  42. 42  parameter  V_CMOS_DISP = 11'd768;                  //CMOS分辨率--行
  43. 43  parameter  H_CMOS_DISP = 11'd1024;                 //CMOS分辨率--列
  44. 44  parameter  TOTAL_H_PIXEL = H_CMOS_DISP + 12'd1216;
  45. 45  parameter  TOTAL_V_PIXEL = V_CMOS_DISP + 12'd504;   
  46. 46                                                                     
  47. 47  //wire define                          
  48. 48  wire         clk_50m                   ;  //50mhz时钟
  49. 49  wire         locked_100m               ;  //时钟锁定信号
  50. 50  wire         locked_300m               ;  //时钟锁定信号
  51. 51  wire         rst_n                     ;  //全局复位                                                               
  52. 52  wire         wr_en                     ;  //DDR3控制器模块写使能
  53. 53  wire  [15:0] wr_data                   ;  //DDR3控制器模块写数据
  54. 54  wire         rdata_req                 ;  //DDR3控制器模块读使能
  55. 55  wire  [15:0] rd_data                   ;  //DDR3控制器模块读数据
  56. 56  wire         cmos_frame_valid          ;  //数据有效使能信号
  57. 57  wire         init_calib_complete       ;  //DDR3初始化完成init_calib_complete
  58. 58  wire         sys_init_done             ;  //系统初始化完成(DDR初始化+摄像头初始化)
  59. 59  wire         cmos_frame_vsync          ;  //输出帧有效场同步信号
  60. 60  wire         lcd_de                    ;  //LCD 数据输入使能
  61. 61  wire         cmos_frame_href           ;  //输出帧有效行同步信号
  62. 62  wire  [10:0] h_disp                    ;  //水平分辨率
  63. 63  wire  [10:0] v_disp                    ;  //垂直分辨率     
  64. 64  wire  [29:0] ddr3_addr_max             ;  //存入DDR3的最大读写地址
  65. 65  wire         clk_in;
  66. 66  
  67. 67  //*****************************************************
  68. 68  //**                    main code
  69. 69  //*****************************************************
  70. 70  //待时钟锁定后产生复位结束信号
  71. 71  assign  rst_n = sys_rst_n & locked_100m & locked_300m;
  72. 72  
  73. 73  //系统初始化完成:DDR3初始化完成
  74. 74  assign  sys_init_done = init_calib_complete;
  75. 75  
  76. 76  //DDR3的最大读写地址
  77. 77  assign  ddr3_addr_max = V_CMOS_DISP * H_CMOS_DISP;
  78. 78     
  79. 79  //ov5640 驱动
  80. 80  ov5640_dri u_ov5640_dri(
  81. 81      .clk               (clk_50m),
  82. 82      .rst_n             (rst_n),
  83. 83  
  84. 84      .cam_pclk          (cam_pclk ),
  85. 85      .cam_vsync         (cam_vsync),
  86. 86      .cam_href          (cam_href ),
  87. 87      .cam_data          (cam_data ),
  88. 88      .cam_rst_n         (cam_rst_n),
  89. 89      .cam_pwdn          (cam_pwdn ),
  90. 90      .cam_scl           (cam_scl  ),
  91. 91      .cam_sda           (cam_sda  ),
  92. 92      
  93. 93      .capture_start     (init_calib_complete),
  94. 94      .cmos_h_pixel      (H_CMOS_DISP),
  95. 95      .cmos_v_pixel      (V_CMOS_DISP),
  96. 96      .total_h_pixel     (TOTAL_H_PIXEL),
  97. 97      .total_v_pixel     (TOTAL_V_PIXEL),
  98. 98      .cmos_frame_vsync  (cmos_frame_vsync),
  99. 99      .cmos_frame_href   (),
  100. 100     .cmos_frame_valid  (cmos_frame_valid),
  101. 101     .cmos_frame_data   (wr_data)
  102. 102     );  
  103. 103     
  104. 104 //ddr控制器
  105. 105 ddr3_control
  106. 106  #(
  107. 107    .C3_NUM_DQ_PINS         (16),
  108. 108    .C3_MEM_ADDR_WIDTH      (14),
  109. 109    .C3_MEM_BANKADDR_WIDTH  (3)
  110. 110    )
  111. 111  u_ddr3_control(
  112. 112   .clk_ddr                (clk_ddr),                              
  113. 113   .clk_100m               (clk_100m),                             
  114. 114   .rst_n                  (sys_rst_n),                           
  115. 115   .mcb3_dram_dq           (mcb3_dram_dq     ),                    
  116. 116   .mcb3_dram_a            (mcb3_dram_a      ),                    
  117. 117   .mcb3_dram_ba           (mcb3_dram_ba     ),                    
  118. 118   .mcb3_dram_ras_n        (mcb3_dram_ras_n  ),                    
  119. 119   .mcb3_dram_cas_n        (mcb3_dram_cas_n  ),                    
  120. 120   .mcb3_dram_we_n         (mcb3_dram_we_n   ),                    
  121. 121   .mcb3_dram_reset_n      (mcb3_dram_reset_n),                    
  122. 122   .mcb3_dram_cke          (mcb3_dram_cke    ),                    
  123. 123   .mcb3_dram_dm           (mcb3_dram_dm     ),                    
  124. 124   .mcb3_dram_udqs         (mcb3_dram_udqs   ),                    
  125. 125   .mcb3_dram_udqs_n       (mcb3_dram_udqs_n ),                    
  126. 126   .mcb3_rzq               (mcb3_rzq         ),                    
  127. 127   .mcb3_zio               (mcb3_zio         ),                    
  128. 128   .mcb3_dram_udm          (mcb3_dram_udm    ),                    
  129. 129   .mcb3_dram_dqs          (mcb3_dram_dqs    ),                    
  130. 130   .mcb3_dram_dqs_n        (mcb3_dram_dqs_n  ),                    
  131. 131   .mcb3_dram_ck           (mcb3_dram_ck     ),                    
  132. 132   .mcb3_dram_ck_n         (mcb3_dram_ck_n   ),                    
  133. 133   .c3_calib_done          (init_calib_complete),                  
  134. 134                                                                  
  135. 135   .ddr3_read_valid        (1'b1 ),                                
  136. 136   .ddr3_pingpang_en       (1'b1),                                 
  137. 137                                                                  
  138. 138   //摄像头                                                        
  139. 139   .clk_write              (cam_pclk),              //写时钟                          
  140. 140   .wr_en                  (cmos_frame_valid),      //写使能                        
  141. 141   .wr_data                (wr_data),               //写数据                        
  142. 142   .wr_length              (H_CMOS_DISP[10:1]),     //一次写长度                          
  143. 143   .wr_max_addr            (ddr3_addr_max),         //写最大地址   
  144. 144   .wr_min_addr            (0),                     //写最小地址                        
  145. 145                                                                             
  146. 146   .clk_read               (pixel_clk),             //读时钟                        
  147. 147   .rd_en                  (rdata_req),             //读使能                        
  148. 148   .rd_max_addr            (ddr3_addr_max),         //读最大地址   
  149. 149   .rd_min_addr            (0),                     //读最小地址                        
  150. 150   .rd_length              (H_CMOS_DISP[10:1]),     //一次读长度                        
  151. 151   .rd_data                (rd_data)                //读数据                        
  152. 152                                                                  
  153. 153   );
  154. 154
  155. 155 //时钟模块
  156. 156 clock u_clock(
  157. 157     .sys_clk      (sys_clk),       //系统输入时钟
  158. 158
  159. 159     .clk_ddr      (clk_ddr),       //ddr运行时钟
  160. 160     .clk_50m      (clk_50m),       //50m时钟
  161. 161     .clk_100m     (clk_100m),      //100m时钟
  162. 162     .locked_100m  (locked_100m),   //时钟稳定信号
  163. 163     .locked_300m  (locked_300m)    //时钟稳定信号
  164. 164     
  165. 165 );
  166. 166
  167. 167 //HDMI驱动显示模块   
  168. 168 hdmi_top u_hdmi_top(
  169. 169     .clk_50m              (clk_50m),  
  170. 170     .pixel_clk            (pixel_clk),  
  171. 171     .sys_rst_n            (sys_init_done & rst_n),
  172. 172     //hdmi接口                  
  173. 173     .tmds_clk_p           (tmds_clk_p   ),   // TMDS 时钟通道
  174. 174     .tmds_clk_n           (tmds_clk_n   ),
  175. 175     .tmds_data_p          (tmds_data_p  ),   // TMDS 数据通道
  176. 176     .tmds_data_n          (tmds_data_n  ),
  177. 177     //用户接口
  178. 178     .h_disp               (h_disp),          //HDMI屏水平分辨率
  179. 179     .v_disp               (v_disp),          //HDMI屏垂直分辨率   
  180. 180     .pixel_xpos           (),
  181. 181     .pixel_ypos           (),      
  182. 182     .data_in              (rd_data),         //数据输入     
  183. 183     .data_req             (rdata_req)        //请求数据输入   
  184. 184 );
  185. 185
  186. 186 endmodule
复制代码

FPGA顶层模块(ov5640_hdmi)例化了以下四个模块:时钟模块(clock)、OV5640驱动模块(ov5640_dri)、DDR控制模块(ddr3_control)和HDMI顶层模块(hdmi_top)。
时钟模块(clock):时钟模块通过调用DCM_CLKGEN IP核实现,共输出3个时钟,频率分别为300Mhz、50Mhz时钟和100Mhz时钟。300Mhz时钟作为DDR控制模块的运行时钟;100Mhz时钟作为DDR控制模块的驱动时钟;50Mhz时钟作为OV5640驱动模块和HDMI顶层模块的驱动时钟。
OV5640驱动模块(ov5640_dri):OV5640驱动模块负责驱动OV5640 SCCB接口总线,将像素时钟驱动下的传感器输出的场同步信号、行同步信号以及8位数据转换成DDR读写控制模块的写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。
DDR控制模块(ddr3_control):DDR读写控制器模块负责驱动DDR片外存储器,缓存图像传感器输出的图像数据。该模块将MIG IP核复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关DDR控制模块的详细介绍请大家参考“DDR读写测试实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供参数和数据请求信号。HDMI顶层模块例化了HDMI驱动模块(video_driver)和RGB转DVI模块(rgbtodvi_top)。HDMI驱动模块负责产生行场信号和数据有效使能信号和像素点的横纵坐标,并将内部信号data_req(数据请求信号)输出至端口,方便从DDR控制器中读取数据。RGB转DVI模块负责将RGB888格式的视频图像转换成TMDS数据输出。有关HDMI驱动模块、RGB转DVI模块的详细介绍请大家参考“HDMI彩条显示实验”章节。
39.5下载验证
编译完工程之后就可以开始下载程序了。将OV5640摄像头模块插在超越者开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,验证OV5640 HDMI实时显示功能。下载完成后HDMI显示器上会显示OV5640摄像头采集到的图像,如下图所示,说明OV5640 HDMI实时显示程序下载验证成功。

图 39.5.1 OV5640 HDMI实时显示图像



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-12-15 05:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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