正点原子开拓者FPGA开发板资料连载第38章OV5640摄像头显示实验
2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-13912-1-1.html
第三十八章 OV5640摄像头RGB TFT-lcd显示实验
在OV5640摄像头VGA显示实验中,我们成功地在VGA显示器上实时显示出了摄像头采集的图
像。本章我们将使用FPGA开发板实现对OV5640的
1)实验平台:正点原子开拓者FPGA 开发板
2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-13912-1-1.html
第三十八章 OV5640摄像头RGB TFT-lcd显示实验
在OV5640摄像头VGA显示实验中,我们成功地在VGA显示器上实时显示出了摄像头采集的图
像。本章我们将使用FPGA开发板实现对OV5640的数字图像采集并通过RGB LCD液晶屏实时显示。
本章包括以下几个部分:
38.1 OV5640简介
38.2 实验任务
38.3 硬件设计
38.4 程序设计
38.5 下载验证
OV5640简介
我们在“OV5640摄像头VGA显示实验”中对OV5640的视频传输时序、SCCB协议以及寄存器
的配置信息等内容作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“OV5640
摄像头VGA显示实验”中的OV5640简介部分。
实验任务
本节实验任务是使用开拓者开发板及OV5640摄像头实现图像采集,并通过正点原子推出的
RGBLCD液晶屏模块实时显示,支持4.3寸480*272、7寸800*480、7寸1024*600、10.1寸1280*800
这些尺寸/分辨率的屏幕。
硬件设计
摄像头扩展接口原理图及OV5640模块说明与“OV5640摄像头VGA显示实验”完全相同,请
参考“OV5640摄像头VGA显示实验”硬件设计部分。RGB TFT-LCD接口部分的硬件设计请参考
“RGB TFT-LCD彩条显示实验”中的硬件设计部分。
由于OV5640、LCD接口和SDRAM引脚数目较多且在前面相应的章节中已经给出它们的管脚列
表,这里不再列出管脚分配。
程序设计
图 38.4.1是根据本章实验任务画出的系统框图。PLL时钟模块为I2C驱动模块、LCD顶层模
块以及SDRAM控制器模块提供驱动时钟;I2C驱动模块和I2C配置模块、图像尺寸配置模块用于
初始化OV5640图像传感器;摄像头采集模块负责采集摄像头图像数据,并且把图像数据写入
SDRAM读写控制模块;SDRAM读写控制模块负责将用户数据写入和读出片外SDRAM存储器中;LCD
顶层模块负责驱动RGB TFT-LCD显示屏。
OV5640摄像头RGB TFT-LCD显示系统框图如下图所示:
图 38.4.1 OV5640摄像头RGB TFT-LCD显示系统框图
顶层模块的原理图如下图所示:
图 38.4.2 顶层模块原理图
由上图可知,I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始
化完成后图像采集模块将采集到的数据写入SDRAM读写控制模块,LCD模块从SDRAM控制模块中
读出数据,完成了数据的采集、缓存与显示。其中图像数据采集模块是在SDRAM和传感器都初
始化完成之后才开始输出数据的,避免了在SDRAM初始化过程中向里面写入数据。
FPGA顶层模块(ov5640_rgb565_lcd)例化了以下六个模块:PLL时钟模块(pll_clk)、
I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov7725_rgb565_cfg)、摄像头图像采集模块
(cmos_capture_data)、图像尺寸配置模块(picture_size)、SDRAM读写控制模块(sdram_top)
和LCD顶层模块(lcd)。
PLL时钟模块(pll_clk):PLL时钟模块通过调用锁相环(PLL)IP核实现,总共输出3个
时钟,频率分别为100Mhz、100Mhz(SDRAM相位偏移时钟)和100Mhz(LCD分频用)时钟。100Mhz
时钟和100Mhz相位偏移时钟作为SDRAM读写控制模块的驱动时钟,最后一个100Mhz时钟作为LCD
顶层模块的驱动时钟。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV5640 SCCB接口总线,用户可根据该模
块提供的用户接口对OV5640的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的
I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
I2C配置模块(i2c_ov5640_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出
的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置
的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV5640的寄存器地址和数
据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成
对OV5640传感器的初始化。有关该模块的详细介绍请大家参考“OV5640摄像头VGA显示实验”
章节。在本章节中对该模块稍加了一些修改,我们会在后面进行讲解。
摄像头图像采集模块(cmos_capture_data):摄像头采集模块在像素时钟的驱动下将传
感器输出的场同步信号、行同步信号以及8位数据转换成SDRAM读写控制模块的写使能信号和16
位写数据信号,完成对OV5640传感器图像的采集。OV7725和OV5640图像输出时序非常相似,有
关该模块的详细介绍请大家参考“OV7725摄像头VGA显示实验”章节。
图像尺寸配置模块(picture_size):图像尺寸配置模块用于配置摄像头输出图像尺寸的
大小,以及设置摄像头输出图像的帧率(每秒输出图像的帧数),此外还完成了SDRAM的读写
结束地址设置。
SDRAM读写控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓
存图像传感器输出的图像数据。该模块将SDRAM复杂的读写操作封装成类似FIFO的用户接口,
非常方便用户的使用。在“SDRAM读写测试实验”的程序中,读写操作地址都是SDRAM的同一存储空间,如果只使用一个存储空间缓存图像数据,那么同一存储空间中会出现两帧图像叠加的
情况,为了避免这一情况,我们在SDRAM的其它BANK中开辟一个相同大小的存储空间,使用乒
乓操作的方式来写入和读取数据,所以本次实验在“SDRAM读写测试实验”的程序里做了一个
小小的改动,有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节,修改部分请大
家参考“OV7725摄像头VGA显示实验”章节。
LCD顶层模块(lcd):LCD顶层模块下例化了以下三个模块:读ID模块(rd_id)、分频模
块(clk_div)、LCD驱动模块(lcd_driver)。
读ID模块(rd_id):读ID模块用于读取连接到开发板上的LCD的ID。
分频模块(clk_div):分频模块用于输出驱动LCD所需要的时钟。由于不同尺寸/分辨率
RGB LCD的驱动时钟频率是不一样的,该模块实现不同LCD的驱动时钟适配。
LCD驱动模块(lcd_driver):LCD驱动模块负责驱动LCD液晶屏,该模块通过读取SDRAM读
写控制模块来输出像素数据,本次实验将LCD驱动模块的内部信号data_req(数据请求信号)
输出至端口,方便从SDRAM控制器中读取数据。有关LCD驱动模块的详细介绍请大家参考“RGB
TFT-LCD彩条显示实验”章节。
下面是顶层模块中参数设置需要注意的地方,顶层模块参数设置代码如下:
55 //parameter define
56 parameter SLAVE_ADDR = 7'h3c ; //OV5640的器件地址7'h3c
57 parameter BIT_CTRL = 1'b1 ; //OV5640的字节地址为16位 0:8位 1:16位
58 parameter CLK_FREQ = 27'd100_000_000; //i2c_dri模块的驱动时钟频率 100MHz
59 parameter I2C_FREQ = 18'd250_000 ; //I2C的SCL时钟频率,不超过400KHz
在代码的第56行定义了OV5640的器件地址,其器件地址为7’h3c;第58行定义了寄存器地
址的位宽,BIT_CTRL=0表示地址位宽为8位,BIT_CTRL=1表示地址位宽为16位。因为OV5640的
地址位宽为16位,所以BIT_CTRL设置为1。
下面是顶层模块里锁相环例化部分:
82 //锁相环
83 pll u_pll(
84 .areset (~sys_rst_n),
85 .inclk0 (sys_clk),
86 .c0 (clk_100m),
87 .c1 (clk_100m_shift),
88 .c2 (clk_100m_lcd),
89 .locked (locked)
90 );
在代码的第88行输出了一个100Mhz的时钟clk_100m_lcd,作为LCD顶层模块(lcd)和I2C
驱动模块(i2c_dri)的驱动时钟。
为了适配现有的RGB LCD屏幕,我们对I2C配置模块的端口部分进行了修改:
92 //I2C配置模块
93 i2c_ov5640_rgb565_cfg u_i2c_cfg(
94 .clk (i2c_dri_clk),
95 .rst_n (rst_n),
96 .i2c_done (i2c_done),
97 .i2c_exec (i2c_exec),
98 .i2c_data (i2c_data),
99 .i2c_rh_wl (i2c_rh_wl), //I2C读写控制信号
100 .i2c_data_r (i2c_data_r),
101 .init_done (cam_init_done),
102 .cmos_h_pixel (cmos_h_pixel), //CMOS水平方向像素个数
103 .cmos_v_pixel (cmos_v_pixel) , //CMOS垂直方向像素个数
104 .total_h_pixel (total_h_pixel), //水平总像素大小
105 .total_v_pixel (total_v_pixel) //垂直总像素大小
106 );
在“OV5640摄像头VGA显示实验”中,cmos_h_pixel、cmos_v_pixel是通过参数传递的方
式将数值传递给I2C配置模块。在本实验中,这两个配置需要依据LCD尺寸的大小而改变。此外,
total_h_pixel及total_v_pixel的参数也需要进行配置,它们会影响到输出图像的帧率。所以,
在代码的第102行至代码的105行,我们添加了4个端口,用于根据LCD的尺寸大小适配摄像头输
出图像的尺寸及帧率。
在顶层模块中例化了图像尺寸配置模块(picture_size),它输出了上一段提到的四个变
量的具体数值:
145 //摄像头图像分辨率设置模块
146 picture_size u_picture_size (
147 .rst_n (rst_n ),
148
149 .ID_lcd (ID_lcd ), //LCD的ID,用于配置摄像头的图像大小
150
151 .cmos_h_pixel (cmos_h_pixel ), //CMOS水平方向像素个数
152 .cmos_v_pixel (cmos_v_pixel ), //CMOS垂直方向像素个数
153 .total_h_pixel (total_h_pixel ), //用于配置HTS寄存器
154 .total_v_pixel (total_v_pixel ), //用于配置VTS寄存器
155 .sdram_max_addr (sdram_max_addr) //sdram读写的最大地址
156 );
模块内部的代码如下:
1 module picture_size (
2 input rst_n ,
3
4 input [15:0] ID_lcd ,
5
6 output reg [12:0] cmos_h_pixel,
7 output reg [12:0] cmos_v_pixel,
8 output reg [12:0] total_h_pixel,
9 output reg [12:0] total_v_pixel,
10 output reg [23:0] sdram_max_addr
11 );
12
13 //parameter define
14 parameter ID_4342 = 0;
15 parameter ID_7084 = 1;
16 parameter ID_7016 = 2;
17 parameter ID_1018 = 5;
18
19 //*****************************************************
20 //** main code
21 //*****************************************************
22
23 //配置摄像头输出图像的尺寸大小
24 always @(*) begin
25 case(ID_lcd )
26 ID_4342 : begin
27 cmos_h_pixel = 13'd480;
28 cmos_v_pixel = 13'd272;
29 sdram_max_addr =23'd130560;
30 end
31 ID_7084 : begin
32 cmos_h_pixel = 13'd800;
33 cmos_v_pixel = 13'd480;
34 sdram_max_addr =23'd384000;
35 end
36 ID_7016 : begin
37 cmos_h_pixel = 13'd1024;
38 cmos_v_pixel = 13'd600;
39 sdram_max_addr =23'd614400;
40 end
41 ID_1018 : begin
42 cmos_h_pixel = 13'd1280;
43 cmos_v_pixel = 13'd800;
44 sdram_max_addr =23'd1024000;
45 end
46 default : begin
47 cmos_h_pixel = 13'd480;
48 cmos_v_pixel = 13'd272;
49 sdram_max_addr =23'd130560;
50 end
51 endcase
52 end
53
54 //对HTS及VTS的配置会影响摄像头输出图像的帧率
55 always @(*) begin
56 case(ID_lcd)
57 ID_4342 : begin
58 total_h_pixel = 13'd1800;
59 total_v_pixel = 13'd1000;
60 end
61 ID_7084 : begin
62 total_h_pixel = 13'd1800;
63 total_v_pixel = 13'd1000;
64 end
65 ID_7016 : begin
66 total_h_pixel = 13'd2200;
67 total_v_pixel = 13'd1000;
68 end
69 ID_1018 : begin
70 total_h_pixel = 13'd2570;
71 total_v_pixel = 13'd980;
72 end
73 default : begin
74 total_h_pixel = 13'd1800;
75 total_v_pixel = 13'd1000;
76 end
77 endcase
78 end
79
80 endmodule
我们通过组合逻辑对变量进行赋值,在代码的第24至第59行,对摄像头输出图像尺寸相关
的参数(cmos_h_pixel、cmos_v_pixel)进行了配置。同时还配置了一帧图像在SDRAM里的结
束缓存地址sdram_max_addr,它是cmos_h_pixel、cmos_v_pixel的乘积。
在代码的61至93行,对影响帧率的参数total_h_pixel、total_v_pixel进行了配置。
在顶层代码例化SDRAM顶层模块的170和179行,我们进行了修改。如下所示,SDRAM顶层模
块的wr_max_addr与rd_max_addr端口和sdram_max_addr信号直连。
158 //SDRAM 控制器顶层模块,封装成FIFO接口
159 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}
160 sdram_top u_sdram_top(
161 .ref_clk (clk_100m), //sdram 控制器参考时钟
162 .out_clk (clk_100m_shift), //用于输出的相位偏移时钟
163 .rst_n (rst_n), //系统复位
164
165 //用户写端口
166 .wr_clk (cam_pclk), //写端口FIFO: 写时钟
167 .wr_en (wr_en), //写端口FIFO: 写使能
168 .wr_data (wr_data), //写端口FIFO: 写数据
169 .wr_min_addr (24'd0), //写SDRAM的起始地址
170 .wr_max_addr (sdram_max_addr), //写SDRAM的结束地址
171 .wr_len (10'd512), //写SDRAM时的数据突发长度
172 .wr_load (~rst_n), //写端口复位: 复位写地址,清空写FIFO
173
174 //用户读端口
175 .rd_clk (clk_lcd), //读端口FIFO: 读时钟
176 .rd_en (rd_en), //读端口FIFO: 读使能
177 .rd_data (rd_data), //读端口FIFO: 读数据
178 .rd_min_addr (24'd0), //读SDRAM的起始地址
179 .rd_max_addr (sdram_max_addr), //读SDRAM的结束地址
180 .rd_len (10'd512), //从SDRAM中读数据时的突发长度
181 .rd_load (~rst_n), //读端口复位: 复位读地址,清空读FIFO
在顶层模块代码的最后,例化了LCD顶层模块(lcd),如下所示:
201 //例化LCD顶层模块
202 lcd u_lcd(
203 .clk (clk_100m_lcd),
204 .rst_n (rst_n),
205
206 .lcd_hs (lcd_hs),
207 .lcd_vs (lcd_vs),
208 .lcd_de (lcd_de),
209 .lcd_rgb (lcd_rgb),
210 .lcd_bl (lcd_bl),
211 .lcd_rst (lcd_rst),
212 .lcd_pclk (lcd_pclk),
213
214 .clk_lcd (clk_lcd),
215
216 .pixel_data (rd_data),
217 .rd_en (rd_en),
218
219 .ID_lcd (ID_lcd)
220 );
LCD顶层模块里例化了读ID模块(rd_id)、分频模块(clk_div)、LCD驱动模块(lcd_driver),
如下所示:
1 module lcd(
2 input clk ,
3 input rst_n ,
4 //RGB LCD接口
5 output lcd_hs , //LCD 行同步信号
6 output lcd_vs , //LCD 场同步信号
7 output lcd_de , //LCD 数据输入使能
8 inout [15:0] lcd_rgb , //LCD RGB565颜色数据
9 output lcd_bl , //LCD 背光控制信号
10 output lcd_rst , //LCD 复位信号
11 output lcd_pclk, //LCD 采样时钟
12
13 output clk_lcd,
14 input [15:0] pixel_data, //像素点数据
15 output rd_en , //请求像素点颜色数据输入
16
17 output [15:0] ID_lcd //LCD的ID
18 );
19
20 //*****************************************************
21 //** main code
22 //*****************************************************
23
24 //RGB565数据输出
25 assign lcd_rgb = lcd_de ? pixel_data : 16'dz;
26
27 //读rgb lcd ID 模块
28 rd_id u_rd_id(
29 .clk (clk),
30 .rst_n (rst_n),
31 .lcd_rgb (lcd_rgb),
32 .ID_lcd (ID_lcd)
33
34 );
35
36 //分频模块,根据不同的LCD ID输出相应的频率的驱动时钟
37 clk_div u_clk_div(
38 .clk (clk),
39 .rst_n (rst_n),
40 .ID_lcd (ID_lcd),
41 .clk_lcd (clk_lcd)
42 );
43
44 //lcd驱动模块
45 lcd_driver u_lcd_driver(
46 .lcd_clk (clk_lcd),
47 .sys_rst_n (rst_n),
48
49 .lcd_hs (lcd_hs),
50 .lcd_vs (lcd_vs),
51 .lcd_de (lcd_de),
52 .lcd_bl (lcd_bl),
53 .lcd_rst (lcd_rst),
54 .lcd_pclk (lcd_pclk),
55
56 .data_req (rd_en), //请求像素点颜色数据输入
57 .pixel_xpos (),
58 .pixel_ypos (),
59 .ID_lcd (ID_lcd)
60 );
61
62 endmodule
在代码的第25行,当lcd_de信号为高电平时,即像素数据有效的时候,输出pixel_data信
号给lcd_rgb。当lcd_de信号为低电平时,给lcd_rgb信号赋值为高阻态。我们就是在当lcd_rgb
信号高阻态的时候,读取LCD的ID。读ID模块的代码如下:
1 module rd_id(
2 input clk ,
3 input rst_n ,
4 input [15:0] lcd_rgb, //像素点数据
5
6 output reg [15:0] ID_lcd
7 );
8
9 //reg define
10 reg ID_rd_en;
11
12 //*****************************************************
13 //** main code
14 //*****************************************************
15
16 //通过读r、g、b信号的最高位来获取LCD的ID
17 always @(posedge clk or negedge rst_n) begin
18 if (!rst_n) begin
19 ID_lcd
20 ID_rd_en
21 end
22 else if(!ID_rd_en) begin
23 ID_lcd
24 ID_rd_en
25 end
26 else
27 ID_lcd
28 end
29
30 endmodule
代码的第17行至28行实现了读取LCD ID的操作,在复位信号拉高后读取一次ID。
在前面,我们提到过不同尺寸的LCD所需的驱动时钟频率是不一样的。比如4.3寸LCD需要
9MHz的时钟,
7寸800*480分辨率的LCD需要33.3MHz的时钟,7寸1024*600分辨率的LCD需要50MHz
的时钟,10.1寸LCD需要70MHz的时钟。为了适配不同尺寸/分辨率的LCD,就需要输出相应的驱
动时钟。分频模块的代码如下:
1 module clk_div(
2 input clk ,
3 input rst_n ,
4 input [15:0] ID_lcd , //LCD的ID
5 output reg clk_lcd //驱动LCD的时钟
6
7 );
8
9 //parameter define
10 parameter ID_4342 = 0;
11 parameter ID_7084 = 1;
12 parameter ID_7016 = 2;
13 parameter ID_1018 = 5;
14
15 //wire define
16 wire clk_33m;
17
18 //reg define
19 reg [1:0] state_33m_0;
20 reg [1:0] state_33m_1;
21 reg [2:0] cnt_10m;
22 reg clk_50m;
23 reg clk_10m;
24
25 //*****************************************************
26 //** main code
27 //*****************************************************
28
29 //50m hz时钟分频
30 always @ (posedge clk or negedge rst_n) begin
31 if(!rst_n)
32 clk_50m
33 else
34 clk_50m
35 end
36
37 //33.3m hz时钟分频
38 always @ (posedge clk ) begin
39 case (state_33m_0)
40 2'b00 : state_33m_0
41 2'b01 : state_33m_0
42 2'b10 : state_33m_0
43 default : state_33m_0
44 endcase
45 end
46
47 always @ (negedge clk ) begin
48 case (state_33m_1)
49 2'b00 : state_33m_1
50 2'b01 : state_33m_1
51 2'b10 : state_33m_1
52 default : state_33m_1
53 endcase
54 end
55
56 assign clk_33m = state_33m_0[1] | state_33m_1[1];
57
58 //10m hz时钟分频
59 always @ (posedge clk or negedge rst_n) begin
60 if(!rst_n)
61 cnt_10m
62 else if(cnt_10m == 3'd4)
63 cnt_10m
64 else
65 cnt_10m
66 end
67
68 always @ (posedge clk or negedge rst_n) begin
69 if(!rst_n)
70 clk_10m
71 else if(cnt_10m == 3'd4)
72 clk_10m
73 else
74 clk_10m
75 end
76
77 //选择输出的时钟
78 always @ ( * ) begin
79 case(ID_lcd)
80 ID_4342 : clk_lcd = clk_10m;
81 ID_7084 : clk_lcd = clk_33m;
82 ID_7016 : clk_lcd = clk_50m;
83 ID_1018 : clk_lcd = clk_50m;
84 default : clk_lcd = clk_10m;
85 endcase
86 end
87
88 endmodule
我们决定把100MHz的输入时钟分频为10MHz、33.3MHz、50Mhz这三个频率的时钟。7寸1024*600分辨率的LCD和10.1寸的LCD共用50MHz的时钟。在代码的第78至90行,根据LCD的ID选
取合适频率的时钟输出。
仿真的结果如下所示:
图 38.4.3 分频模块仿真结果图
为了能够驱动不同的LCD,LCD驱动模块也需要进行适当的修改:
1 module lcd_driver(
2 input lcd_clk, //lcd模块驱动时钟
3 input sys_rst_n, //复位信号
4 //RGB LCD接口
5 output lcd_hs, //LCD 行同步信号
6 output lcd_vs, //LCD 场同步信号
7 output lcd_de, //LCD 数据输入使能
8 output lcd_bl, //LCD 背光控制信号
9 output lcd_rst, //LCD 复位信号
10 output lcd_pclk, //LCD 采样时钟
11
12 output data_req , //请求像素点颜色数据输入
13 output [10:0] pixel_xpos, //像素点横坐标
14 output [10:0] pixel_ypos, //像素点纵坐标
15 input [15:0] ID_lcd //LCD的ID
16 );
17
18 //parameter define
19 // 4.3' 480*272
20 parameter H_SYNC_4342 = 11'd41; //行同步
21 parameter H_BACK_4342 = 11'd2; //行显示后沿
22 parameter H_DISP_4342 = 11'd480; //行有效数据
23 parameter H_FRONT_4342 = 11'd2; //行显示前沿
24 parameter H_TOTAL_4342 = 11'd525; //行扫描周期
25
26 parameter V_SYNC_4342 = 11'd10; //场同步
27 parameter V_BACK_4342 = 11'd2; //场显示后沿
28 parameter V_DISP_4342 = 11'd272; //场有效数据
29 parameter V_FRONT_4342 = 11'd2; //场显示前沿
30 parameter V_TOTAL_4342 = 11'd286; //场扫描周期
31
32 // 7' 800*480
33 parameter H_SYNC_7084 = 11'd128; //行同步
34 parameter H_BACK_7084 = 11'd88; //行显示后沿
35 parameter H_DISP_7084 = 11'd800; //行有效数据
36 parameter H_FRONT_7084 = 11'd40; //行显示前沿
37 parameter H_TOTAL_7084 = 11'd1056; //行扫描周期
38
39 parameter V_SYNC_7084 = 11'd2; //场同步
40 parameter V_BACK_7084 = 11'd33; //场显示后沿
41 parameter V_DISP_7084 = 11'd480; //场有效数据
42 parameter V_FRONT_7084 = 11'd10; //场显示前沿
43 parameter V_TOTAL_7084 = 11'd525; //场扫描周期
44
45 // 7' 1024*600
46 parameter H_SYNC_7016 = 11'd20; //行同步
47 parameter H_BACK_7016 = 11'd140; //行显示后沿
48 parameter H_DISP_7016 = 11'd1024; //行有效数据
49 parameter H_FRONT_7016 = 11'd160; //行显示前沿
50 parameter H_TOTAL_7016 = 11'd1344; //行扫描周期
51
52 parameter V_SYNC_7016 = 11'd3; //场同步
53 parameter V_BACK_7016 = 11'd20; //场显示后沿
54 parameter V_DISP_7016 = 11'd600; //场有效数据
55 parameter V_FRONT_7016 = 11'd12; //场显示前沿
56 parameter V_TOTAL_7016 = 11'd635; //场扫描周期
57
58 // 10.1' 1280*800
59 parameter H_SYNC_1018 = 11'd10; //行同步
60 parameter H_BACK_1018 = 11'd80; //行显示后沿
61 parameter H_DISP_1018 = 11'd1280; //行有效数据
62 parameter H_FRONT_1018 = 11'd70; //行显示前沿
63 parameter H_TOTAL_1018 = 11'd1440; //行扫描周期
64
65 parameter V_SYNC_1018 = 11'd3; //场同步
66 parameter V_BACK_1018 = 11'd10; //场显示后沿
67 parameter V_DISP_1018 = 11'd800; //场有效数据
68 parameter V_FRONT_1018 = 11'd10; //场显示前沿
69 parameter V_TOTAL_1018 = 11'd823; //场扫描周期
70
71 //LCD的ID
72 parameter ID_4342 = 0;
73 parameter ID_7084 = 1;
74 parameter ID_7016 = 2;
75 parameter ID_1018 = 5;
76
77 //reg define
78 reg [10:0] cnt_h;
79 reg [10:0] cnt_v;
80 reg [10:0] h_sync ;
81 reg [10:0] h_back ;
82 reg [10:0] h_disp ;
83 reg [10:0] h_total;
84 reg [10:0] v_sync ;
85 reg [10:0] v_back ;
86 reg [10:0] v_disp ;
87 reg [10:0] v_total;
88
89 //wire define
90 wire lcd_en;
91
92 //*****************************************************
93 //** main code
94 //*****************************************************
95 assign lcd_bl = 1'b1; //RGB LCD显示模块背光控制信号
96 assign lcd_rst = 1'b1; //RGB LCD显示模块系统复位信号
97 assign lcd_pclk = lcd_clk; //RGB LCD显示模块采样时钟
98
99 //RGB LCD 采用数据输入使能信号同步时,行场同步信号需要拉高
100 assign lcd_de = lcd_en; //LCD输入的颜色数据采用数据输入使能信号同步
101 assign lcd_hs = 1'b1;
102 assign lcd_vs = 1'b1;
103
104 //使能RGB565数据输出
105 assign lcd_en = (((cnt_h >= h_sync h_back) && (cnt_h
106 &&((cnt_v >= v_sync v_back) && (cnt_v
107 ? 1'b1 : 1'b0;
108
109 //请求像素点颜色数据输入
110 assign data_req = (((cnt_h >= h_sync h_back-1'b1) && (cnt_h
111 && ((cnt_v >= v_sync v_back) && (cnt_v
112 ? 1'b1 : 1'b0;
113
114 //像素点坐标
115 assign pixel_xpos = data_req ? (cnt_h - (h_sync h_back - 1'b1)) : 11'd0;
116 assign pixel_ypos = data_req ? (cnt_v - (v_sync v_back - 1'b1)) : 11'd0;
117
118 //行场时序参数
119 always @(*) begin
120 case(ID_lcd)
121 ID_4342 : begin
122 h_sync = H_SYNC_4342;
123 h_back = H_BACK_4342;
124 h_disp = H_DISP_4342;
125 h_total = H_TOTAL_4342;
126 v_sync = V_SYNC_4342;
127 v_back = V_BACK_4342;
128 v_disp = V_DISP_4342;
129 v_total = V_TOTAL_4342;
130 end
131 ID_7084 : begin
132 h_sync = H_SYNC_7084;
133 h_back = H_BACK_7084;
134 h_disp = H_DISP_7084;
135 h_total = H_TOTAL_7084;
136 v_sync = V_SYNC_7084;
137 v_back = V_BACK_7084;
138 v_disp = V_DISP_7084;
139 v_total = V_TOTAL_7084;
140 end
141 ID_7016 : begin
142 h_sync = H_SYNC_7016;
143 h_back = H_BACK_7016;
144 h_disp = H_DISP_7016;
145 h_total = H_TOTAL_7016;
146 v_sync = V_SYNC_7016;
147 v_back = V_BACK_7016;
148 v_disp = V_DISP_7016;
149 v_total = V_TOTAL_7016;
150 end
151 ID_1018 : begin
152 h_sync = H_SYNC_1018;
153 h_back = H_BACK_1018;
154 h_disp = H_DISP_1018;
155 h_total = H_TOTAL_1018;
156 v_sync = V_SYNC_1018;
157 v_back = V_BACK_1018;
158 v_disp = V_DISP_1018;
159 v_total = V_TOTAL_1018;
160 end
161 default : begin
162 h_sync = H_SYNC_4342;
163 h_back = H_BACK_4342;
164 h_disp = H_DISP_4342;
165 h_total = H_TOTAL_4342;
166 v_sync = V_SYNC_4342;
167 v_back = V_BACK_4342;
168 v_disp = V_DISP_4342;
169 v_total = V_TOTAL_4342;
170 end
171 endcase
172 end
173
174 //行计数器对像素时钟计数
175 always @(posedge lcd_clk or negedge sys_rst_n) begin
176 if (!sys_rst_n)
177 cnt_h
178 else begin
179 if(cnt_h
180 cnt_h
181 else
182 cnt_h
183 end
184 end
185
186 //场计数器对行计数
187 always @(posedge lcd_clk or negedge sys_rst_n) begin
188 if (!sys_rst_n)
189 cnt_v
190 else if(cnt_h == h_total - 1'b1) begin
191 if(cnt_v
192 cnt_v
193 else
194 cnt_v
195 end
196 end
197
198 endmodule
在代码的第20至70行,定义了四种RGB LCD屏的时序参数。在代码的第120行至第185行,
根据LCD的ID对参数变量进行赋值。
本章实验程序设计与“OV5640摄像头VGA显示实验”比较近似,除了例举出来的部分,其
余模块(除PLL时钟模块外)完全相同。有关本章实验的详细设计详情请大家参考“OV5640摄
像头VGA显示实验”章节。
下载验证
首先我们打开OV5640摄像头RGB TFT-LCD显示实验工程,在工程所在的路径下打开
ov5640_rgb565_lcd/par文件夹,在里面找到“ov5640_rgb565_lcd.qpf”并双击打开。注意工
程所在的路径名只能由字母、数字以及下划线组成,不能出现中文、空格以及特殊字符等。工
程打开后如图 38.5.1所示:
图 38.5.1 OV5640摄像头RGB TFT-LCD显示实验工程
然后将OV5640摄像头插入开发板上的摄像头扩展接口(注意摄像头镜头朝外);将FPC 排
线一端与ALIENTEK的RGB接口模块上的J1接口连接,另一端与开拓者开发板上的J1接口连接;
连接时,先掀开FPC连接器上的黑色翻盖,将FPC排线蓝色面朝上插入连接器,最后将黑色翻盖
压下以固定FPC排线。
最后将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开
关。
接下来我们下载程序,验证OV5640摄像头RGB TFT-LCD实时显示功能。
工程打开后通过点击工具栏中的“Programmer”图标打开下载界面,通过“Add File”按
钮选择ov5640_rgb565_lcd/par/output_files目录下的“ov5640_rgb565_lcd.sof”文件。开
发板电源打开后,在程序下载界面点击“Hardware Setup”,在弹出的对话框中选择当前的硬
件连接为“USB-Blaster[USB-0]”。然后点击“Start”将工程编译完成后得到的sof文件下载
到开发板中,如图 38.5.所示:
图 38.5.2 程序下载完成界面
下载完成后观察显示器的显示图像如图 38.5.所示,说明OV5640摄像头LCD显示程序下载
验证成功。
图 38.5.3 RGB TFT-LCD实时显示图像
文章评论