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

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

50.1简介
我们在“OV5640摄像头HDMI灰度显示实验”中对YUV灰度显示作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“OV5640摄像头HDMI灰度显示实验”中的简介部分。
50.2实验任务
本节实验任务是使用新起点开发板达到OV5640摄像头采集RGB565格式的数据,RGB565格式的数据通过算法转换,将数据格式转换为YCbCr格式,然后通过LCD屏实时显示灰度图的目的。
50.3硬件设计
本章节中硬件设计与OV5640的LCD显示实验完全相同,此处不再赘述。
50.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 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 //LCD
25 output lcd_hs , //LCD 行同步信号
26 output lcd_vs , //LCD 场同步信号
27 output lcd_de , //LCD 数据输入使能
28 inout [15:0] lcd_rgb , //LCD RGB565颜色数据
29 output lcd_bl , //LCD 背光控制信号
30 output lcd_rst , //LCD 复位信号
31 output lcd_pclk //LCD 采样时钟
32 );
33
34 //parameter define
35 parameter SLAVE_ADDR = 7’h3c ; //OV5640的器件地址7’h3c
36 parameter BIT_CTRL = 1’b1 ; //OV5640的字节地址为16位 0:8位 1:16位
37 parameter CLK_FREQ = 27’d50_000_000 ; //i2c_dri模块的驱动时钟频率
38 parameter I2C_FREQ = 18’d250_000 ; //I2C的SCL时钟频率,不超过400KHz
39
40 //wire define
41 wire clk_100m ; //100mhz时钟,SDRAM操作时钟
42 wire clk_100m_shift ; //100mhz时钟,SDRAM相位偏移时钟
43 wire clk_50m_lcd ; //100mhz时钟,LCD顶层模块时钟
44 wire clk_lcd ;
45 wire locked ;
46 wire rst_n ;
47 wire sys_init_done ; //系统初始化完成(sdram初始化+摄像头初始化)
48
49 wire i2c_exec ; //I2C触发执行信号
50 wire [23:0] i2c_data ; //I2C要配置的地址与数据(高8位地址,低8位数据)
51 wire i2c_done ; //I2C寄存器配置完成信号
52 wire i2c_dri_clk ; //I2C操作时钟
53 wire [ 7:0] i2c_data_r ; //I2C读出的数据
54 wire i2c_rh_wl ; //I2C读写控制信号
55 wire cam_init_done ; //摄像头初始化完成
56
57 wire wr_en ; //sdram_ctrl模块写使能
58 wire [15:0] wr_data ; //sdram_ctrl模块写数据
59 wire rd_en ; //sdram_ctrl模块读使能
60 wire [15:0] rd_data ; //sdram_ctrl模块读数据
61 wire sdram_init_done ; //SDRAM初始化完成
62
63 wire [15:0] lcd_id ; //LCD的ID
64 wire [12:0] cmos_h_pixel ; //CMOS水平方向像素个数
65 wire [12:0] cmos_v_pixel ; //CMOS垂直方向像素个数
66 wire [12:0] total_h_pixel ; //水平总像素大小
67 wire [12:0] total_v_pixel ; //垂直总像素大小
68 wire [23:0] sdram_max_addr ; //sdram读写的最大地址
69 wire post_frame_vsync ; //处理后的场信号
70 wire post_frame_hsync ; //处理后的行信号
71 wire post_frame_de ; //处理后的数据使能
72 wire [15:0] post_rgb ; //处理后的数据
73
74 //*****************************************************
75 //** main code
76 //*****************************************************
77
78 assign rst_n = sys_rst_n & locked;
79 //系统初始化完成:SDRAM和摄像头都初始化完成
80 //避免了在SDRAM初始化过程中向里面写入数据
81 assign sys_init_done = sdram_init_done & cam_init_done;
82 //电源休眠模式选择 0:正常模式 1:电源休眠模式
83 assign cam_pwdn = 1’b0;
84 assign cam_rst_n = 1’b1;
85
86 //锁相环
87 pll 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 //摄像头图像分辨率设置模块
98 picture_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[23:8]),
142 .i2c_data_w (i2c_data[7:0] ),
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[1:0],row_addr[12:0],col_addr[8:0]}
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_top u_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屏的驱动信号的输出,同时为其他模块提供屏体参数、场同步信号和数据请求信号。
50.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实时显示灰度图像

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值