搜索
bottom↓
回复: 0

《新起点V2之FPGA开发指南》第四十四章 MT9V034摄像头HDMI显示实验

[复制链接]

出0入234汤圆

发表于 2021-10-22 12:46:31 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2021-10-30 10:49 编辑

1)实验平台:正点原子新起点V2FPGA开发板
2)  章节摘自【正点原子】《新起点之FPGA开发指南 V2.1》
3)购买链接:https://detail.tmall.com/item.htm?id=609758951113
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-328002-1-1.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:712557122
1.png


2.jpg


3.png


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

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

1.1简介
       在“MT9V034摄像头TFT-LCD显示实验”中对MT9V034的视频传输时序、两线式接口总线协议以及寄存器的配置信息等内容作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“MT9V034摄像头TFT-LCD显示实验”中的MT9V034简介部分。
1.2实验任务
       本节实验任务是使用新起点开发板及MT9V034摄像头实现图像采集,通过HDMI接口驱动HDMI显示器,并实时显示出图像。
1.3硬件设计
       摄像头扩展接口原理图及MT9V034模块说明与“MT9V034摄像头TFT-LCD显示实验”完全相同,请参考“MT9V034摄像头TFT-LCD显示实验”硬件设计部分。HDMI接口部分的硬件设计请参考“HDMI彩条显示实验”中的硬件设计部分。
由于MT9V034、HDMI接口和SDRAM引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里不再列出管脚分配。
1.4程序设计
       图 44.4.1是根据本章实验任务画出的系统框图。对比“MT9V034摄像头RGB-LCD显示实验”的系统框图可以发现,本次实验只是把LCD顶层模块替换成了HDMI顶层模块,并将图像采集模块中的图片裁剪模块去掉了,其余模块(除时钟模块外)完全相同。之所以本节实验将图片裁剪模块去掉是因为本次实验所用HDMI显示器的分辨率是大于摄像头分辨率的,所以只需要在HDMI驱动模块中稍微改下数据请求即可,改动部分和OV7725 HDMI显示实验一摸一样,这里就不再详细讲解了。时钟模块(由两个pll锁相环组成,一个负责提供LCD、SDRAM和IIC模块的参考时钟;另一个负责提供HDMI模块的像素时钟与5倍频时钟)用于为I2C驱动模块、HDMI顶层模块以及SDRAM控制模块提供驱动时钟;I2C驱动模块和I2C配置模块用于初始化MT9V034图像传感器;摄像头采集模块负责采集摄像头图像数据,并且把图像数据写入SDRAM控制模块中;SDRAM控制模块负责将用户数据写入和读出片外SDRAM存储器;HDMI顶层模块负责驱动HDMI显示器。本章使用的HDMI显示器其分辨率为1280*800,而MT9V034传感器的本次实验所配置的分辨率为640*480,所以HDMI显示器需要填充黑色的像素点。
第四十四章 MT9V034摄像头HDMI显示实验1127.png

图 44.4.1 顶层系统框图

       由上图可知,时钟模块为HDMI顶层模块、SDRAM控制模块以及I2C驱动模块提供驱动时钟。I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后图像采集模块将采集到的数据写入SDRAM控制模块,HDMI顶层模块从SDRAM控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在SDRAM和传感器都初始化完成之后才开始输出数据的,避免了在SDRAM初始化过程中向里面写入数据。
       顶层代码如下所示:
  1. 1   module mt9v034_hdmi(   
  2. 2       input                 sys_clk     ,  //系统时钟
  3. 3       input                 sys_rst_n   ,  //系统复位,低电平有效
  4. 4       //摄像头接口                       
  5. 5       //cmos interface
  6. 6       output                  cmos_scl  ,  //cmos i2c clock
  7. 7       inout                   cmos_sda  ,  //cmos i2c data
  8. 8       input                   cmos_vsync,  //cmos vsync
  9. 9       input                   cmos_href ,  //cmos hsync refrence
  10. 10      input                   cmos_pclk ,  //cmos pxiel clock
  11. 11      input   [7:0]           cmos_data ,  //cmos data   
  12. 12      output                 cmos_reset ,  //cmos reset   
  13. 13      output                 cmos_pwdn  ,  //cmos pwer down  
  14. 14      //SDRAM接口
  15. 15      output                sdram_clk   ,  //SDRAM 时钟
  16. 16      output                sdram_cke   ,  //SDRAM 时钟有效
  17. 17      output                sdram_cs_n  ,  //SDRAM 片选
  18. 18      output                sdram_ras_n ,  //SDRAM 行有效
  19. 19      output                sdram_cas_n ,  //SDRAM 列有效
  20. 20      output                sdram_we_n  ,  //SDRAM 写有效
  21. 21      output       [1:0]    sdram_ba    ,  //SDRAM Bank地址
  22. 22      output       [1:0]    sdram_dqm   ,  //SDRAM 数据掩码
  23. 23      output       [12:0]   sdram_addr  ,  //SDRAM 地址
  24. 24      inout        [15:0]   sdram_data  ,  //SDRAM 数据                        
  25. 25      //hdmi接口               
  26. 26      output                tmds_clk_p  ,  // TMDS 时钟通道
  27. 27      output                tmds_clk_n  ,
  28. 28      output  [2:0]         tmds_data_p ,  // TMDS 数据通道
  29. 29      output  [2:0]         tmds_data_n     
  30. 30      
  31. 31  );
  32. 32  
  33. 33  //parameter define                     
  34. 34  parameter  SLAVE_ADD = 7'b1001_000     ;  //slave  address           
  35. 35  parameter  BIT_CTRL   = 1'b0           ;  //MT9V034的字节地址为8位  0:8位 1:16位
  36. 36  parameter  DATA_CTRL  = 1'b1           ;  // MT9V034的数据为16位  0:8位 1:16位
  37. 37  parameter  CLK_FREQ   = 26'd50_000_000 ;  //i2c_dri模块的驱动时钟频率 50.0MHz
  38. 38  parameter  I2C_FREQ   = 18'd250_000    ;  //I2C的SCL时钟频率,不超过400KHz
  39. 39                                                                          
  40. 40  //wire define                          
  41. 41  wire         clk_100m                  ;  //100mhz时钟
  42. 42  wire         clk_100m_shift            ;  //100mhz时钟,相位偏移时钟
  43. 43  wire         clk_50m                   ;  //50mhz时钟,提供给lcd驱动时钟
  44. 44  wire         clk_24m                   ;
  45. 45  wire         locked                    ;  //时钟锁定信号
  46. 46  wire         rst_n                     ;  //全局复位                                    
  47. 47  wire         i2c_exec                  ;  //I2C触发执行信号
  48. 48  wire  [15:0] i2c_data                  ;  //I2C要配置的地址与数据(高8位地址,低8位数据)         
  49. 49  wire         cam_init_done             ;  //摄像头初始化完成
  50. 50  wire         i2c_done                  ;  //I2C寄存器配置完成信号
  51. 51  wire         i2c_dri_clk               ;  //I2C操作时钟                                 
  52. 52  wire         wr_en                     ;  //sdram控制器模块写使能
  53. 53  wire  [15:0] wr_data                   ;  //sdram控制器模块写数据
  54. 54  wire         rdata_req                 ;  //sdram控制器模块读使能
  55. 55  wire  [15:0] rd_data                   ;  //sdram控制器模块读数据
  56. 56  wire         cmos_frame_valid          ;  //数据有效使能信号
  57. 57  wire         init_calib_complete       ;  //sdram初始化完成init_calib_complete
  58. 58  wire         sys_init_done             ;  //系统初始化完成(sdram初始化+摄像头初始化)
  59. 59  wire         cmos_frame_vsync          ;  //输出帧有效场同步信号
  60. 60  wire         cmos_frame_href           ;  //输出帧有效行同步信号
  61. 61  wire  [9:0]  pixel_xpos_w              ;  //像素点横坐标
  62. 62  wire  [9:0]  pixel_ypos_w              ;  //像素点纵坐标   
  63. 63  wire         lcd_clk                   ;  //分频产生的LCD 采样时钟
  64. 64  wire  [10:0] h_disp                    ;  //LCD屏水平分辨率
  65. 65  wire  [10:0] v_disp                    ;  //LCD屏垂直分辨率     
  66. 66  wire  [10:0] h_pixel                   ;  //存入sdram的水平分辨率        
  67. 67  wire  [10:0] v_pixel                   ;  //存入sdram的屏垂直分辨率
  68. 68  wire  [15:0] lcd_id                    ;  //LCD屏的ID号
  69. 69  wire  [7:0]  cmos_frame_data           ;  //cmos frame data output
  70. 70  wire  [7:0]  i2c_addr                  ;  
  71. 71  wire  [15:0] i2c_wr_data               ;  
  72. 72  wire  [27:0] sdram_addr_max            ;  //存入sdram的最大读写地址
  73. 73  wire         cmos_xclk                 ;
  74. 74  wire         locked_hdmi               ;
  75. 75  wire         hdmi_clk                  ;
  76. 76  wire         hdmi_clk_5                ;
  77. 77  //*****************************************************
  78. 78  //**                    main code
  79. 79  //*****************************************************
  80. 80  
  81. 81  //待时钟锁定后产生复位结束信号
  82. 82  assign  rst_n = sys_rst_n & locked & locked_hdmi;
  83. 83  
  84. 84  //系统初始化完成:sdram初始化完成
  85. 85  assign  sys_init_done = sdram_init_done  & i2c_config_done;
  86. 86  
  87. 87  assign  cmos_reset  = 1'b1;     //cmos work state (50us delay)
  88. 88  assign  cmos_pwdn   = 1'b0;     //cmos power on
  89. 89  
  90. 90  pll_clk pll_clk_inst (
  91. 91      .areset ( ~sys_rst_n   ),
  92. 92      .inclk0 ( sys_clk      ),
  93. 93      .c0     ( clk_50m      ),
  94. 94      .c1     ( clk_100m     ),
  95. 95      .c2     (clk_100m_shift),
  96. 96      .locked ( locked       )
  97. 97      );
  98. 98  
  99. 99  pll_hdmi    pll_hdmi_inst (
  100. 100     .areset             ( ~sys_rst_n  ),
  101. 101     .inclk0             ( sys_clk     ),
  102. 102     .c0                 ( hdmi_clk    ),//hdmi pixel clock 71Mhz
  103. 103     .c1                 ( hdmi_clk_5  ),//hdmi pixel clock*5 355Mhz
  104. 104     .locked             ( locked_hdmi )
  105. 105     );
  106. 106
  107. 107 i2c_cfg  u_i2c_cfg(
  108. 108     .clk          (i2c_dri_clk    ),
  109. 109     .rst_n        (sys_rst_n      ),
  110. 110     .i2c_done     (i2c_done       ),
  111. 111     .i2c_exec     (i2c_exec       ),
  112. 112     .i2c_addr     (i2c_addr       ),
  113. 113     .i2c_wr_data  (i2c_wr_data    ),               
  114. 114     .cfg_done     (i2c_config_done)
  115. 115     );
  116. 116
  117. 117 //I2C驱动模块
  118. 118 i2c_dri #(
  119. 119     .SLAVE_ADDR         (SLAVE_ADD ),    //参数传递
  120. 120     .CLK_FREQ           (CLK_FREQ  ),              
  121. 121     .I2C_FREQ           (I2C_FREQ  )
  122. 122     )
  123. 123 u_i2c_dr(
  124. 124     .clk                (clk_50m   ),
  125. 125     .rst_n              (sys_rst_n ),
  126. 126
  127. 127     .i2c_exec           (i2c_exec  ),   
  128. 128     .bit_ctrl           (BIT_CTRL  ),   
  129. 129     .data_ctrl          (DATA_CTRL ),
  130. 130     .i2c_rh_wl          (0),            //固定为0,只用到了IIC驱动的写操作   
  131. 131     .i2c_addr           ({8'b0,i2c_addr}),   
  132. 132     .i2c_data_w         (i2c_wr_data),   
  133. 133     .i2c_data_r         (),   
  134. 134     .i2c_done           (i2c_done  ),   
  135. 135     .scl                (cmos_scl  ),   
  136. 136     .sda                (cmos_sda  ),   
  137. 137     .dri_clk            (i2c_dri_clk)       //I2C操作时钟
  138. 138     );
  139. 139
  140. 140 //图像采集顶层模块
  141. 141 cmos_data_top u_cmos_data_top(
  142. 142     .rst_n                 (sys_init_done),         //系统初始化完成之后再开始采集数据
  143. 143     .clk_cmos              (clk_24m),               //24MHz CMOS Driver clock input   
  144. 144     .cam_pclk              (cmos_pclk),            
  145. 145     .cmos_xclk             (cmos_xclk),             //24MHz drive clock   
  146. 146     .cam_vsync             (cmos_vsync),
  147. 147     .cam_href              (cmos_href),
  148. 148     .cam_data              (cmos_data),
  149. 149     .lcd_id                (lcd_id),
  150. 150     .h_pixel               (h_pixel),
  151. 151     .v_pixel               (v_pixel),
  152. 152     .sdram_addr_max        (sdram_addr_max),   
  153. 153     .cmos_frame_vsync      (cmos_frame_vsync),
  154. 154     .cmos_frame_href       (cmos_frame_href),
  155. 155     .cmos_frame_valid      (cmos_frame_valid),      //数据有效使能信号
  156. 156     .cmos_frame_data       (wr_data)                //有效数据
  157. 157     );
  158. 158     
  159. 159 //SDRAM 控制器顶层模块,封装成FIFO接口
  160. 160 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}
  161. 161 sdram_top u_sdram_top(
  162. 162     .ref_clk            (clk_100m),         //sdram 控制器参考时钟
  163. 163     .out_clk            (clk_100m_shift),   //用于输出的相位偏移时钟
  164. 164     .rst_n              (rst_n),            //系统复位
  165. 165                                             
  166. 166     //用户写端口                              
  167. 167     .wr_clk             (cmos_pclk),        //写端口FIFO: 写时钟
  168. 168     .wr_en              (cmos_frame_valid), //写端口FIFO: 写使能
  169. 169     .wr_data            (wr_data),          //写端口FIFO: 写数据
  170. 170     .wr_min_addr        (24'd0),            //写SDRAM的起始地址
  171. 171     .wr_max_addr        (sdram_addr_max),   //写SDRAM的结束地址
  172. 172     .wr_len             (10'd512),          //写SDRAM时的数据突发长度
  173. 173     .wr_load            (~rst_n),           //写端口复位: 复位写地址,清空写FIFO
  174. 174                                             
  175. 175     //用户读端口                              
  176. 176     .rd_clk             (hdmi_clk),         //读端口FIFO: 读时钟
  177. 177     .rd_en              (rdata_req),        //读端口FIFO: 读使能
  178. 178     .rd_data            (rd_data),          //读端口FIFO: 读数据
  179. 179     .rd_min_addr        (24'd0),            //读SDRAM的起始地址
  180. 180     .rd_max_addr        (sdram_addr_max),   //读SDRAM的结束地址
  181. 181     .rd_len             (10'd512),          //从SDRAM中读数据时的突发长度
  182. 182     .rd_load            (~rst_n),           //读端口复位: 复位读地址,清空读FIFO
  183. 183                                                
  184. 184     //用户控制端口                                
  185. 185     .sdram_read_valid   (1'b1),             //SDRAM 读使能
  186. 186     .sdram_pingpang_en  (1'b1),             //SDRAM 乒乓操作使能
  187. 187     .sdram_init_done    (sdram_init_done),  //SDRAM 初始化完成标志
  188. 188                                             
  189. 189     //SDRAM 芯片接口                                
  190. 190     .sdram_clk          (sdram_clk),        //SDRAM 芯片时钟
  191. 191     .sdram_cke          (sdram_cke),        //SDRAM 时钟有效
  192. 192     .sdram_cs_n         (sdram_cs_n),       //SDRAM 片选
  193. 193     .sdram_ras_n        (sdram_ras_n),      //SDRAM 行有效
  194. 194     .sdram_cas_n        (sdram_cas_n),      //SDRAM 列有效
  195. 195     .sdram_we_n         (sdram_we_n),       //SDRAM 写有效
  196. 196     .sdram_ba           (sdram_ba),         //SDRAM Bank地址
  197. 197     .sdram_addr         (sdram_addr),       //SDRAM 行/列地址
  198. 198     .sdram_data         (sdram_data),       //SDRAM 数据
  199. 199     .sdram_dqm          (sdram_dqm)         //SDRAM 数据掩码
  200. 200     );   
  201. 201     
  202. 202 //例化HDMI顶层模块
  203. 203 hdmi_top u_hdmi_top(
  204. 204     .hdmi_clk       (hdmi_clk     ),
  205. 205     .hdmi_clk_5     (hdmi_clk_5   ),
  206. 206     .rst_n          (rst_n        ),
  207. 207                 
  208. 208     .rd_data        (rd_data      ),
  209. 209     .rd_en          (rdata_req),
  210. 210     .h_disp         (h_disp       ),     
  211. 211     .v_disp         (v_disp       ),   
  212. 212     .pixel_xpos     (),
  213. 213     .pixel_ypos     (),
  214. 214     .video_vs       (),  
  215. 215     .tmds_clk_p     (tmds_clk_p   ),
  216. 216     .tmds_clk_n     (tmds_clk_n   ),
  217. 217     .tmds_data_p    (tmds_data_p  ),
  218. 218     .tmds_data_n    (tmds_data_n  )
  219. 219     );   
  220. 220
  221. 221 endmodule
复制代码

       FPGA顶层模块(mt9v034_hdmi)例化了以下7个模块:时钟模块(时钟模块由两个锁相环组成,分别是pll_clk和pll_hdmi)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_cfg)、图像采集模块(cmos_data_top)、SDRAM控制模块(sdram_top)和HDMI顶层模块(hdmi_top)。
       时钟模块(pll_clk和pll_hdmi):时钟模块通过调用PLL IP核实现,其中pll_clk为SDRAM控制模块以及I2C驱动模块提供驱动时钟,pll_hdmi 主要是为HDMI模块提供像素时钟和5倍像素时钟(频率分别是71Mhz和355Mhz)。
       I2C驱动模块(i2c_dri):I2C驱动模块负责驱动MT9V034的两线式接口总线,用户可根据该模块提供的用户接口可以很方便的对MT9V034的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
       I2C配置模块(i2c_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址和数据,同时该模块输出MT9V034的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对MT9V034传感器的配置。
       图像采集模块(cmos_data_top):在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据信号进行采集,在摄像头数据稳定后输出场同步信号、行同步信号以及8位数据信号,以提供给SDRAM控制模块所使用。
       SDRAM控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存图像传感器输出的图像数据。该模块将SDRAM复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关SDRAM控制模块的详细介绍请大家参考“SDRAM读写实验”章节。
       HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供LCD屏参数、场同步信号和数据请求信号。HDMI顶层模块例化了HDMI驱动模块(video_driver)和HDMI驱动转换顶层模块(dvi_transmitter_top)。HDMI驱动模块负责产生行场信号和数据有效使能信号和像素点的横纵坐标,并将内部信号data_req(数据请求信号)输出至端口,方便从SDRAM控制器中读取数据。HDMI驱动转换顶层模块负责将RGB565格式的视频图像转换成TMDS数据输出。有关HDMI驱动模块、HDMI驱动转换顶层模块的详细介绍请大家参考“HDMI彩条显示实验”章节,HDMI显示模块详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
1.5下载验证
       编译完工程之后就可以开始下载程序了。将MT9V034摄像头模块插在新起点开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,验证MT9V034 HDMI实时显示功能。下载完成后观察HDMI显示器显示的图案如下图所示,说明MT9V034 HDMI实时显示程序下载验证成功。
第四十四章 MT9V034摄像头HDMI显示实验13360.png

图 44.5.1 HDMI实时显示图像

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-27 07:29

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

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