搜索
bottom↓
回复: 0

《新起点V2之FPGA开发指南》第五十章 OV5640摄像头LCD灰度显示实验

[复制链接]

出0入234汤圆

发表于 2021-10-28 16:13:39 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2021-10-30 10:53 编辑

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


第五十章 OV5640摄像头LCD灰度显示实验

       前面的实验介绍了OV5640摄像头的HDMI灰度显示实验,在本次实验中,将摄像头采集的RGB565格式数据到转换为YUV格式的数据,转换后的灰度数据送到LCD显示。
       本章包括以下几个部分:
       1.1简介
       1.2实验任务
       1.3硬件设计
       1.4程序设计
       1.5下载验证

1.1简介
       我们在“OV5640摄像头HDMI灰度显示实验”中对YUV灰度显示作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“OV5640摄像头HDMI灰度显示实验”中的简介部分。
1.2实验任务
       本节实验任务是使用新起点开发板达到OV5640摄像头采集RGB565格式的数据,RGB565格式的数据通过算法转换,将数据格式转换为YCbCr格式,然后通过LCD屏实时显示灰度图的目的。
1.3硬件设计
       本章节中硬件设计与OV5640的LCD显示实验完全相同,此处不再赘述。
1.4程序设计
       根据实验任务,首先设计如图 50.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头HDMI灰度显示实验”的整体架构。本次实验包括以下模块:时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、图像尺寸配置模块、摄像头采集模块、图像处理模块和LCD顶层模块。其中时钟模块、SDRAM控制器模块、IIC驱动模块、IIC配置模块、摄像头采集模块和图像处理模块本次实验没有做任何修改,这些模块在“OV5640摄像头HDMI灰度显示实验”中已经说明过,这里不再详述,只是将HDMI顶层模块替换成了LCD顶层模块,并添加了图像尺寸配置模块。
       OV5640摄像头LCD灰度显示系统框图如下图所示:
第五十章 OV5640摄像头LCD灰度显示实验740.png

图 50.4.1 顶层系统框图

       由上图可知,时钟模块(pll)为LCD顶层模块、SDRAM控制模块以及IIC驱动模块提供驱动时钟。IIC驱动模块和IIC配置模块控制着传感器初始化的开始与结束,传感器初始化完成后将采集到的数据写入摄像头采集模块。数据在摄像头采集模块处理完成后写入图像处理模块,图像处理模块将摄像头数据进行处理后存入SDRAM控制模块。顶层模块从SDRAM控制模块中读出数据并驱动LCD屏显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在SDRAM和传感器都初始化完成之后才开始输出数据的,避免了在SDRAM初始化过程中向里面写入数据。
       顶层模块代码如下所示:
  1. 1   module ov5640_lcd_yuv(   
  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   ,  //cmos 电源休眠模式选择信号
  11. 11      output        cam_scl    ,  //cmos SCCB_SCL线
  12. 12      inout         cam_sda    ,  //cmos SCCB_SDA线
  13. 13      //SDRAM
  14. 14      output        sdram_clk  ,  //SDRAM 时钟
  15. 15      output        sdram_cke  ,  //SDRAM 时钟有效
  16. 16      output        sdram_cs_n ,  //SDRAM 片选
  17. 17      output        sdram_ras_n,  //SDRAM 行有效
  18. 18      output        sdram_cas_n,  //SDRAM 列有效
  19. 19      output        sdram_we_n ,  //SDRAM 写有效
  20. 20      output [1:0]  sdram_ba   ,  //SDRAM Bank地址
  21. 21      output [1:0]  sdram_dqm  ,  //SDRAM 数据掩码
  22. 22      output [12:0] sdram_addr ,  //SDRAM 地址
  23. 23      inout  [15:0] sdram_data ,  //SDRAM 数据   
  24. 24      //LCD                  
  25. 25      output        lcd_hs     ,  //LCD 行同步信号
  26. 26      output        lcd_vs     ,  //LCD 场同步信号
  27. 27      output        lcd_de     ,  //LCD 数据输入使能
  28. 28      inout  [15:0] lcd_rgb    ,  //LCD RGB565颜色数据
  29. 29      output        lcd_bl     ,  //LCD 背光控制信号
  30. 30      output        lcd_rst    ,  //LCD 复位信号
  31. 31      output        lcd_pclk      //LCD 采样时钟
  32. 32      );
  33. 33  
  34. 34  //parameter define
  35. 35  parameter SLAVE_ADDR = 7'h3c          ; //OV5640的器件地址7'h3c
  36. 36  parameter BIT_CTRL   = 1'b1           ; //OV5640的字节地址为16位  0:8位 1:16位
  37. 37  parameter CLK_FREQ   = 27'd50_000_000 ; //i2c_dri模块的驱动时钟频率
  38. 38  parameter I2C_FREQ   = 18'd250_000    ; //I2C的SCL时钟频率,不超过400KHz
  39. 39  
  40. 40  //wire define
  41. 41  wire        clk_100m           ;  //100mhz时钟,SDRAM操作时钟
  42. 42  wire        clk_100m_shift     ;  //100mhz时钟,SDRAM相位偏移时钟
  43. 43  wire        clk_50m_lcd        ;  //100mhz时钟,LCD顶层模块时钟
  44. 44  wire        clk_lcd            ;  
  45. 45  wire        locked             ;
  46. 46  wire        rst_n              ;
  47. 47  wire        sys_init_done      ;  //系统初始化完成(sdram初始化+摄像头初始化)
  48. 48      
  49. 49  wire        i2c_exec           ;  //I2C触发执行信号
  50. 50  wire [23:0] i2c_data           ;  //I2C要配置的地址与数据(高8位地址,低8位数据)         
  51. 51  wire        i2c_done           ;  //I2C寄存器配置完成信号
  52. 52  wire        i2c_dri_clk        ;  //I2C操作时钟
  53. 53  wire [ 7:0] i2c_data_r         ;  //I2C读出的数据
  54. 54  wire        i2c_rh_wl          ;  //I2C读写控制信号
  55. 55  wire        cam_init_done      ;  //摄像头初始化完成
  56. 56                              
  57. 57  wire        wr_en              ;  //sdram_ctrl模块写使能
  58. 58  wire [15:0] wr_data            ;  //sdram_ctrl模块写数据
  59. 59  wire        rd_en              ;  //sdram_ctrl模块读使能
  60. 60  wire [15:0] rd_data            ;  //sdram_ctrl模块读数据
  61. 61  wire        sdram_init_done    ;  //SDRAM初始化完成
  62. 62      
  63. 63  wire [15:0] lcd_id             ;  //LCD的ID
  64. 64  wire [12:0] cmos_h_pixel       ;  //CMOS水平方向像素个数
  65. 65  wire [12:0] cmos_v_pixel       ;  //CMOS垂直方向像素个数
  66. 66  wire [12:0] total_h_pixel      ;  //水平总像素大小
  67. 67  wire [12:0] total_v_pixel      ;  //垂直总像素大小
  68. 68  wire [23:0] sdram_max_addr     ;  //sdram读写的最大地址
  69. 69  wire        post_frame_vsync   ;  //处理后的场信号
  70. 70  wire        post_frame_hsync   ;  //处理后的行信号
  71. 71  wire        post_frame_de      ;  //处理后的数据使能  
  72. 72  wire [15:0] post_rgb           ;  //处理后的数据
  73. 73  
  74. 74  //*****************************************************
  75. 75  //**                    main code
  76. 76  //*****************************************************
  77. 77  
  78. 78  assign  rst_n = sys_rst_n & locked;
  79. 79  //系统初始化完成:SDRAM和摄像头都初始化完成
  80. 80  //避免了在SDRAM初始化过程中向里面写入数据
  81. 81  assign  sys_init_done = sdram_init_done & cam_init_done;
  82. 82  //电源休眠模式选择 0:正常模式 1:电源休眠模式
  83. 83  assign  cam_pwdn  = 1'b0;
  84. 84  assign  cam_rst_n = 1'b1;
  85. 85  
  86. 86  //锁相环
  87. 87  pll u_pll(
  88. 88      .areset             (~sys_rst_n    ),
  89. 89      .inclk0             (sys_clk       ),
  90. 90              
  91. 91      .c0                 (clk_100m      ),
  92. 92      .c1                 (clk_100m_shift),
  93. 93      .c2                 (clk_50m_lcd   ),
  94. 94      .locked             (locked        )
  95. 95      );
  96. 96      
  97. 97  //摄像头图像分辨率设置模块
  98. 98  picture_size u_picture_size (
  99. 99      .clk                (clk_50m_lcd   ),
  100. 100     .rst_n              (rst_n         ),
  101. 101     .id_lcd             (lcd_id        ),   //LCD的ID,用于配置摄像头的图像大小                        
  102. 102     .cmos_h_pixel       (cmos_h_pixel  ),   //摄像头水平方向分辨率
  103. 103     .cmos_v_pixel       (cmos_v_pixel  ),   //摄像头垂直方向分辨率  
  104. 104     .total_h_pixel      (total_h_pixel ),   //用于配置HTS寄存器
  105. 105     .total_v_pixel      (total_v_pixel ),   //用于配置VTS寄存器
  106. 106     .sdram_max_addr     (sdram_max_addr)    //sdram读写的最大地址
  107. 107     );
  108. 108     
  109. 109 //I2C配置模块
  110. 110 i2c_ov5640_rgb565_cfg u_i2c_cfg(
  111. 111     .clk                (i2c_dri_clk   ),
  112. 112     .rst_n              (rst_n         ),
  113. 113            
  114. 114     .i2c_exec           (i2c_exec      ),
  115. 115     .i2c_data           (i2c_data      ),
  116. 116     .i2c_rh_wl          (i2c_rh_wl     ),  //I2C读写控制信号
  117. 117     .i2c_done           (i2c_done      ),
  118. 118     .i2c_data_r         (i2c_data_r    ),   
  119. 119                 
  120. 120     .cmos_h_pixel       (cmos_h_pixel  ),  //CMOS水平方向像素个数
  121. 121     .cmos_v_pixel       (cmos_v_pixel  ),  //CMOS垂直方向像素个数
  122. 122     .total_h_pixel      (total_h_pixel ),  //水平总像素大小
  123. 123     .total_v_pixel      (total_v_pixel ),  //垂直总像素大小
  124. 124         
  125. 125     .init_done          (cam_init_done )
  126. 126     );   
  127. 127
  128. 128 //I2C驱动模块
  129. 129 i2c_dri #(
  130. 130     .SLAVE_ADDR         (SLAVE_ADDR    ), //参数传递
  131. 131     .CLK_FREQ           (CLK_FREQ      ),              
  132. 132     .I2C_FREQ           (I2C_FREQ      )
  133. 133     )
  134. 134 u_i2c_dr(
  135. 135     .clk                (clk_50m_lcd   ),
  136. 136     .rst_n              (rst_n         ),
  137. 137
  138. 138     .i2c_exec           (i2c_exec      ),   
  139. 139     .bit_ctrl           (BIT_CTRL      ),   
  140. 140     .i2c_rh_wl          (i2c_rh_wl     ), //固定为0,只用到了IIC驱动的写操作   
  141. 141     .i2c_addr           (i2c_data[23:8]),   
  142. 142     .i2c_data_w         (i2c_data[7:0] ),   
  143. 143     .i2c_data_r         (i2c_data_r    ),   
  144. 144     .i2c_done           (i2c_done      ),
  145. 145     
  146. 146     .scl                (cam_scl       ),   
  147. 147     .sda                (cam_sda       ),   
  148. 148
  149. 149     .dri_clk            (i2c_dri_clk   )  //I2C操作时钟
  150. 150     );
  151. 151
  152. 152 //CMOS图像数据采集模块
  153. 153 cmos_capture_data u_cmos_capture_data(    //系统初始化完成之后再开始采集数据
  154. 154     .rst_n              (rst_n & sys_init_done),
  155. 155     
  156. 156     .cam_pclk           (cam_pclk ),
  157. 157     .cam_vsync          (cam_vsync),
  158. 158     .cam_href           (cam_href ),
  159. 159     .cam_data           (cam_data ),         
  160. 160     
  161. 161     .cmos_frame_vsync   (cmos_frame_vsync),
  162. 162     .cmos_frame_href    (cmos_frame_href),
  163. 163     .cmos_frame_valid   (wr_en    ),    //数据有效使能信号
  164. 164     .cmos_frame_data    (wr_data  )     //有效数据
  165. 165     );
  166. 166     
  167. 167  //图像处理模块
  168. 168 vip u_vip(
  169. 169     //module clock
  170. 170     .clk              (cam_pclk),           // 时钟信号
  171. 171     .rst_n            (rst_n    ),          // 复位信号(低有效)
  172. 172     //图像处理前的数据接口
  173. 173     .pre_frame_vsync  (cmos_frame_vsync   ),
  174. 174     .pre_frame_hsync  (cmos_frame_href   ),
  175. 175     .pre_frame_de     (wr_en   ),
  176. 176     .pre_rgb          (wr_data),
  177. 177     .xpos             (0   ),
  178. 178     .ypos             (0   ),
  179. 179     //图像处理后的数据接口
  180. 180     .post_frame_vsync (post_frame_vsync ),  // 场同步信号
  181. 181     .post_frame_hsync ( ),                  // 行同步信号
  182. 182     .post_frame_de    (post_frame_de ),     // 数据输入使能
  183. 183     .post_rgb         (post_rgb)            // RGB565颜色数据
  184. 184
  185. 185 );      
  186. 186
  187. 187 //SDRAM 控制器顶层模块,封装成FIFO接口
  188. 188 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}
  189. 189 sdram_top u_sdram_top(
  190. 190     .ref_clk            (clk_100m),         //sdram 控制器参考时钟
  191. 191     .out_clk            (clk_100m_shift),   //用于输出的相位偏移时钟
  192. 192     .rst_n              (rst_n),            //系统复位
  193. 193                                             
  194. 194     //用户写端口                              
  195. 195     .wr_clk             (cam_pclk),         //写端口FIFO: 写时钟
  196. 196     .wr_en              (post_frame_de),    //写端口FIFO: 写使能
  197. 197     .wr_data            (post_rgb),         //写端口FIFO: 写数据
  198. 198     .wr_min_addr        (24'd0),            //写SDRAM的起始地址
  199. 199     .wr_max_addr        (sdram_max_addr),   //写SDRAM的结束地址
  200. 200     .wr_len             (10'd512),          //写SDRAM时的数据突发长度
  201. 201     .wr_load            (~rst_n),           //写端口复位: 复位写地址,清空写FIFO
  202. 202                                             
  203. 203     //用户读端口                              
  204. 204     .rd_clk             (lcd_clk),          //读端口FIFO: 读时钟
  205. 205     .rd_en              (rd_en),            //读端口FIFO: 读使能
  206. 206     .rd_data            (rd_data),          //读端口FIFO: 读数据
  207. 207     .rd_min_addr        (24'd0),            //读SDRAM的起始地址
  208. 208     .rd_max_addr        (sdram_max_addr),   //读SDRAM的结束地址
  209. 209     .rd_len             (10'd512),          //从SDRAM中读数据时的突发长度
  210. 210     .rd_load            (~rst_n),           //读端口复位: 复位读地址,清空读FIFO
  211. 211                                                
  212. 212     //用户控制端口                                
  213. 213     .sdram_read_valid   (1'b1),             //SDRAM 读使能
  214. 214     .sdram_pingpang_en  (1'b1),             //SDRAM 乒乓操作使能
  215. 215     .sdram_init_done    (sdram_init_done),  //SDRAM 初始化完成标志
  216. 216                                             
  217. 217     //SDRAM 芯片接口                                
  218. 218     .sdram_clk          (sdram_clk),        //SDRAM 芯片时钟
  219. 219     .sdram_cke          (sdram_cke),        //SDRAM 时钟有效
  220. 220     .sdram_cs_n         (sdram_cs_n),       //SDRAM 片选
  221. 221     .sdram_ras_n        (sdram_ras_n),      //SDRAM 行有效
  222. 222     .sdram_cas_n        (sdram_cas_n),      //SDRAM 列有效
  223. 223     .sdram_we_n         (sdram_we_n),       //SDRAM 写有效
  224. 224     .sdram_ba           (sdram_ba),         //SDRAM Bank地址
  225. 225     .sdram_addr         (sdram_addr),       //SDRAM 行/列地址
  226. 226     .sdram_data         (sdram_data),       //SDRAM 数据
  227. 227     .sdram_dqm          (sdram_dqm)         //SDRAM 数据掩码
  228. 228     );
  229. 229
  230. 230 //LCD顶层模块
  231. 231 lcd_rgb_top  u_lcd_rgb_top(
  232. 232     .sys_clk               (clk_50m_lcd  ),
  233. 233     .sys_rst_n             (rst_n ),
  234. 234     .sys_init_done         (sys_init_done),     
  235. 235                        
  236. 236     //lcd接口                           
  237. 237     .lcd_id                (lcd_id),                //LCD屏的ID号
  238. 238     .lcd_hs                (lcd_hs),                //LCD 行同步信号
  239. 239     .lcd_vs                (lcd_vs),                //LCD 场同步信号
  240. 240     .lcd_de                (lcd_de),                //LCD 数据输入使能
  241. 241     .lcd_rgb               (lcd_rgb),               //LCD 颜色数据
  242. 242     .lcd_bl                (lcd_bl),                //LCD 背光控制信号
  243. 243     .lcd_rst               (lcd_rst),               //LCD 复位信号
  244. 244     .lcd_pclk              (lcd_pclk),              //LCD 采样时钟
  245. 245     .lcd_clk               (lcd_clk),               //LCD 驱动时钟
  246. 246     //用户接口                     
  247. 247     .out_vsync             (rd_vsync),              //lcd场信号
  248. 248     .h_disp                (),                      //行分辨率  
  249. 249     .v_disp                (),                      //场分辨率  
  250. 250     .pixel_xpos            (),
  251. 251     .pixel_ypos            (),      
  252. 252     .data_in               (rd_data),               //rfifo输出数据
  253. 253     .data_req              (rd_en)                  //请求数据输入
  254. 254     );   
  255. 255
  256. 256 endmodule  
复制代码

       FPGA顶层模块(ov5640_lcd_yuv)例化了以下八个模块:时钟模块(pll)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov5640_rgb565_cfg)、图像尺寸配置模块(picture_size)、图像采集模块(cmos_capture_data)、图像处理模块(vip)、SDRAM控制模块(sdram_top)和LCD顶层模块(lcd_rgb_top)。
       时钟模块:时钟模块通过调用PLL IP核实现,共输出3个时钟,频率分别为100M时钟、100M偏移-75度时钟和50M时钟。100Mhz时钟作为SDRAM控制模块的驱动时钟,100M偏移-75度时钟用来输出给外部SDRAM芯片使用,50Mhz时钟作为I2C驱动模块和LCD顶层模块的驱动时钟。
       I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV5640 SCCB接口总线,用户可根据该模块提供的用户接口可以很方便的对OV5640的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
       I2C配置模块(i2c_ov5640_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV5640的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对OV5640传感器的初始化。
       图像采集模块(cmos_capture_data):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成SDRAM读写控制模块的写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。OV5640和OV7725图像输出时序非常相似,有关该模块的详细介绍请大家参考“OV7725摄像头LCD显示实验”章节。
       图像处理模块(vip):对采集后的图像数据进行处理,并将处理后的数据存入SDRAM控制模块。有关该模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。
       SDRAM控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存图像传感器输出的图像数据。有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节。
        LCD顶层模块(lcd_rgb_top):LCD顶层模块负责驱动LCD屏的驱动信号的输出,同时为其他模块提供屏体参数、场同步信号和数据请求信号。
1.5下载验证
        首先将FPC排线一端与RGB-LCD模块上的J1接口连接,另一端与新起点开发板上的RGB-LCD接口连接。连接时,先掀开FPC连接器上的黑色翻盖,将FPC排线蓝色面朝上插入连接器,最后将黑色翻盖压下以固定FPC排线,如图 50.5.1和图 50.5.2所示。
第五十章 OV5640摄像头LCD灰度显示实验13649.png

图 50.5.1 正点原子RGBLCD模块FPC连接器

第五十章 OV5640摄像头LCD灰度显示实验13722.png

图 50.5.2 新起点开发板连接RGB-LCD液晶屏

       接下来分别连接JTAG接口和电源线,并打开电源开关。
       最后将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。
       接下来我们下载程序,验证OV5640 RGB-LCD灰度显示功能。下载完成后观察RGB-LCD模块显示的图案如下图所示,说明OV5640 RGB-LCD灰度显示程序下载验证成功。
第五十章 OV5640摄像头LCD灰度显示实验13958.png

图 50.5.3 LCD实时显示灰度图像

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

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

本版积分规则

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

GMT+8, 2024-4-24 21:22

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

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