正点原子 发表于 2021-10-28 16:13:39

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

本帖最后由 正点原子 于 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








第五十章 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灰度显示系统框图如下图所示:

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

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

图 50.5.2 新起点开发板连接RGB-LCD液晶屏
       接下来分别连接JTAG接口和电源线,并打开电源开关。
       最后将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。
       接下来我们下载程序,验证OV5640 RGB-LCD灰度显示功能。下载完成后观察RGB-LCD模块显示的图案如下图所示,说明OV5640 RGB-LCD灰度显示程序下载验证成功。

图 50.5.3 LCD实时显示灰度图像
页: [1]
查看完整版本: 《新起点V2之FPGA开发指南》第五十章 OV5640摄像头LCD灰度显示实验