OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 995|回复: 0

[国产FPGA] 《ATK-DFPGL22G 之FPGA开发指南》第四十三章 MT9V034摄像头RGB-LCD显示实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4666
金钱
4666
注册时间
2019-5-8
在线时间
1224 小时
发表于 2023-12-23 15:11:16 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-12-22 16:51 编辑

第四十三章 MT9V034摄像头RGB-LCD显示实验


1)实验平台:正点原子 ATK-DFPGL22G开发板

2) 章节摘自【正点原子】ATK-DFPGL22G之FPGA开发指南_V1.0


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz-PGL22G.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)FPGA技术交流QQ群:435699340

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

MT9V034是ON Semiconductor(安森美半导体)公司生产的一颗CMOS图像传感器,该传感器功耗低、可靠性高以及采集速率快,主要应用于机器视觉,双目视觉,宽温度工业场合等领域。本章我们将使用FPGA开发板实现对MT9V034的数字图像采集并通过LCD实时显示。
本章包括以下几个部分:      
1.1        简介
1.2        实验任务
1.3        硬件设计
1.4        软件设计
1.5        下载验证

1.1 简介
MT9V034是一款1/3英寸单芯片图像传感器,其感光阵列最大可达到752*480,能实现最快60fps VGA分辨率的图像采集,具有全局曝光和高动态范围(HDR)操作。这款CMOS图像传感器具有安森美半导体的突破性功能,实现了CCD图像质量的低噪声和CMOS成像技术(基于信噪比和低光灵敏度),同时保持固有尺寸、成本和CMOS的集成优势。下表为几个摄像头的功能对比。
QQ截图20231222163410.png
表 43.1.1 摄像头对比
通过上述的对比可以看出,相对于其他2款摄像头MT9V034的优势在于HDR模式和全局曝光。HDR模式的原理是根据不同的曝光时间的LDR(Low-Dynamic Range)图像,利用每个曝光时间相对应最佳细节的LDR图像来合成最终HDR图像,与普通的图像相比,可以提供更多的动态范围和图像细节。下图是线性模式和HDR模式的对比图。                             
image001.png
图43.1.1 HDR模式

image002.png
图43.1.2 线性模式
通过对比可以发现,开启了HDR,会使拍到的图像亮度比较高的地方变暗,亮度比较低的地方变亮,总的来说就是使图像显示的更均衡。
卷帘曝光的原理是通过Sensor逐行曝光的方式实现的。在曝光开始的时候,Sensor逐行扫描逐行进行曝光,直至所有像素点都被曝光。与卷帘曝光不同,全局曝光整幅场景在同一时间曝光实现的,Sensor所有像素点同时收集光线,同时曝光。下面为两种模式的对比图。
image003.png
图43.1.3 全局曝光拍摄图

image004.png
图43.1.4 卷帘曝光拍摄图
当拍摄快速移动的物体时,全局曝光拍摄到的物体比较清晰,不会发生形变,而卷帘曝光拍摄的图片会出现部分曝光(partial exposure)、斜坡图形(skew)、晃动(wobble) 等现象,也就是传说中的果冻了。这是全局曝光其优势的一面,相对于卷帘曝光也有其劣势的一面。当全局曝光的曝光时间长(如大于500μs)时,其噪点情况严重,而运用卷帘曝光后,图片会有更低的噪声和更快的帧速。
下图为MT9V034的功能框图:
image005.png
图43.1.5 MT9V034功能框图
由上图可知,除了传统的并行逻辑输出,MT9V034还具有串行低压差分信号(LVDS)输出。该传感器可以在立体声相机中操作,并且该传感器被指定为立体声主机时,可以合并来自本身的立体声,还可以将从属传感器的数据合并为一个串行LVDS流。本次实验只采用传统的并行逻辑输出。
MT9V034通过两线串行接口将寄存器写入MT9V034和从中读取,以此来配置窗口大小和行场分辨率等寄存器。MT9V034是具有四个可能ID(0x90、0x98、0xB0和0xB8)由S_CTRL_ADR0和S_CTRL_ADR1输入引脚确定,本次实验所用的MT9V034的写器件ID是0x90。下图是器件ID的相关内容。
image007.png
图43.1.6器件地址
MT9V034使用的是两线式接口总线,该接口总线包括SCLK串行时钟输入线和SDATA串行双向数据线,分别相当于IIC协议的SCL信号线和SDA信号线。本次实验所用的两线式接口总线兼容IIC协议,所以不对相关协议详细介绍,有关IIC协议的详细介绍请大家参考“EEPROM读写实验”章节。
两线式接口总线的写传输协议如下图所示:
image009.png
图43.1.7 写传输协议
上图中的ADDR是由7位器件地址和1位读写控制位构成(0:写 1:读),MT9V034的器件地址为7’h5c,所以在写传输协议中,ID Address(W)= 8’hb8(器件地址左移1位,低位补0);R0x09为8位寄存器地址,在MT9V034的数据手册中有些寄存器是可改写的,有些是只读的,只有可改写的寄存器才能正确写入;Write Data为16位写数据,每一个寄存器地址对应16位的配置数据。上图中的第9位ACK表示从机应答,该位是由从机(此处指MT9V034)发出应答信号来响应主机表示当前器件地址、寄存器地址和写数据是否传输完成,但是从机有可能不发出应答信号,因此主机(此处指FPGA)在此必须判断此处是否有应答,有应答即说明当前传输完成,无应答表示传输未完成。
我们可以发现,MT9V034的两线式接口总线和IIC写传输协议是极为相似的,只是在两线式接口总线写传输协议中,一个寄存器地址写入16位数据,而IIC写传输协议一个地址只写入8位数据。两线式接口总线的读传输协议和IIC有些差异,在IIC读传输协议中,一个寄存器地址只读出8位数据;而两线式接口总线传输协议中一个寄存器地址只读出16位数据,下图为两线式接口总线的读传输协议。
image011.png
图43.1.8 SCCB写传输协议
由上图可知,两线式接口总线读传输协议分为两个部分。第一部分是写器件地址和寄存器地址,即先进行一次虚写操作,通过这种虚写操作使地址指针指向虚写操作中寄存器地址的位置,当然虚写操作也可以通过前面介绍的写传输协议来完成。第二部分是读器件地址和读数据,此时读取到的数据才是寄存器地址对应的数据,注意ID Address(R) = 8’hB9(器件地址左移1位,低位补1)。上图中的NACK位由主机(这里指FPGA)产生,由于两线式接口总线不支持连续读写,因此NACK位必须为高电平。
MT9V034在上电后是存在默认寄存器的,即上电后就可以输出752x480分辨率的图像,如果大家需要其他的分辨率或模式就必须先对传感器进行初始化,可通过配置寄存器使其工作在预期的工作模式,以得到较好画质的图像。因为两线式接口总线的写传输协议和IIC几乎相同,因此我们可以直接使用IIC的驱动程序来配置摄像头。当然这么多寄存器也并非都需要配置,很多寄存器可以采用默认的值。ON Semiconductor公司提供了MT9V034的数据手册(位于开发板所随附的资料“7_硬件资料/7_MT9V034资料/MT9V034数据手册.pdf”),如果某些寄存器不知道如何配置可以参考此手册,下表是本程序用到的关键寄存器的配置说明。
QQ截图20231222163533.png
QQ截图20231222163459.png
表 43.1.2 MT9V034关键寄存器配置说明

MT9V034的寄存器较多,对于其它寄存器的描述可以参MT9V034的寄存器配置手册(位于开发板所随附的资料“7_硬件资料/7_MT9V034资料/MT9V034寄存器配置说明手册.pdf”)。
下图为MT9V034的一些特性。
image013.png
图 43.1.9 MT9V034的特性
从上图可以看出,MT9V034的输入时钟频率的范围是13Mhz~27Mhz;本次实验摄像头的输入时钟为24Mhz,是由外部晶振提供的;两线式接口总线的SCLK的时钟频率最大为400KHz。
image015.png
图 43.1.10 PIXCLK和SYSCLK的关系
结合图 43.1.10和图 43.1.9可知,PIXCLK和SYSCLK是同频不同相的2个时钟,本次实验摄像头的输入时钟为24Mhz,所以摄像头的输出时钟也为24Mhz。
MT9V034在并行逻辑输出的模式下仅支持10bit的YUV(亮度参量和色度参量分开表示的像素格式),不支持其他格式。由于摄像头采集的图像最终要在LCD上显示,且ATK-DFPGL22G开发板上的数据接口为RGB888格式(详情请参考“LCD彩条显示实验”章节),因此必须将MT9V034摄像头输出的YUV格式的图像像素数据转换为RGB888格式。下图为摄像头输出的行时序图。
image017.png
图43.1.11 行时序图
LINE_VALID:数据有效使能。当其为高时,输出的数据为有效数据。
PIXCLK:像素时钟。由MT9V034产生的对外输出的时钟信号。
DOUT:有效数据。摄像头采集得到的像素数据,本次实验取其高8位。
image019.png
图43.1.12 场时序图
image021.png
图43.1.13 信号含义
INE_VALID:数据有效使能。当其为高时,输出的数据为有效数据。
FRAME_VALID:帧(场)同步信号。当此信号有效的时候就表示开始显示新的一帧数据。

1.2 实验任务
本节实验任务是使用ATK-DFPGL22G开发板及MT9V034摄像头实现图像采集,并通过RGB-LCD接口驱动RGB-LCD液晶屏(支持目前正点原子推出的所有RGB-LCD屏),并实时显示出图像。

1.3 硬件设计
ATK-DFPGL22G开发板上有一个摄像头扩展接口,该接口可以用来连接MT9V034/OV5640等摄像头模块,摄像头扩展接口原理图如下图所示:
image023.png
图 43.3.1 摄像头扩展接口原理图
ATK-MT9V034是正点原子推出的一款高性能36W像素高清摄像头模块。该模块通过2*9排针(2.54mm间距)同外部连接,我们将摄像头的排针直接插在开发板上的摄像头接口即可。
前面说过,MT9V034在YUV模式中有效数据是D[9:0],而我们的摄像头排针上数据引脚的个数是8位,而摄像头排针上的8位数据连接的就是MT9V034传感器的D[9:2],所以我们直接使用摄像头排针上的8位数据引脚即可。
需要注意的是,由图 43.3.1可知,摄像头扩展口的第18个引脚定义为CMOS_PWDN,而我们的MT9V034摄像头模块的STB(CMOS_PWDN)引脚固定为低电平,也就是一直处于正常工作模式。MT9V034摄像头接口的第18个引脚定义为EXP,这个引脚是摄像头外部触发脉冲的引脚,只在快照模式下启用它。MT9V034摄像头模块内部自带24M晶振的,所以不需要FPGA输出时钟给摄像头。
由于LCD接口和DDR3引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里只列出摄像头相关管脚分配,如下表所示:
QQ截图20231222163544.png
表 43.3.1 MT9V034摄像头RGB-LCD显示实验管脚分配
MT9V034摄像头与OV7725摄像头的约束几乎相同,只是C2引脚的cam_sgm_ctrl信号改为cam_stb信号,除了信号名改变了,其余约束没有任何改变,所以这里不再赘述约束文件。

1.4 程序设计
对比“OV7725摄像头RGB-LCD显示实验”的系统框图可以发现,本次实验只是把外设OV7725模块替换成了MT9V034模块,替换了图像采集模块和IIC配置模块,修改了IIC驱动模块,其余模块基本相同。
替换图像采集模块和修改图像采集顶层模块的原因在于OV7725摄像头输出的是RGB565格式16bit数据,而MT9V034输出的是YUV格式的8bit数据;替换IIC配置模块和修改IIC驱动模块的原因在于OV7725的一个寄存器地址只写8bit数据,而MT9V034的一个寄存器地址可以写16bit数据。
下图是根据本章实验任务画出的系统框图:
image025.png
图43.4.1 顶层系统框图
由上图可知,时钟模块(pll_clk)为LCD顶层模块、DDR3控制模块以及I2C驱动模块提供驱动时钟。I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后图像采集模块将采集到的数据写入DDR3控制模块,LCD顶层模块从DDR3控制模块中读出数据,完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
MT9V034虽然在上电后不配置寄存器也能正常工作,但是此时输出的分辨率可能不是实验需要的分辨率,所以必须通过配置寄存器的值来达到实验所需要的分辨率。配置寄存器的协议和I2C协议在写操作时几乎一样,所以需要一个I2C驱动模块。为了使MT9V034在期望的模式下运行并且提高图像显示效果,需要配置较多的寄存器,这么多寄存器的地址与参数需要单独放在一个模块,因此还需要一个寄存配置信息的I2C配置模块。在摄像头配置完成后,开始输出图像数据,因此需要一个摄像头图像采集模块来采集图像;采集到的图像先进入DDR3存储器进行缓存,最后LCD顶层模块读取DDR3缓存的数据以达到最终实时显示的效果。
顶层模块的代码如下:
  1. 1   module mt9v034_lcd(
  2. 2        input            sys_clk          ,
  3. 3        input            sys_rst_n        ,
  4. 4        //lcd接口                        
  5. 5        output           lcd_hs           ,  //LCD 行同步信号
  6. 6        output           lcd_vs           ,  //LCD 场同步信号
  7. 7        output           lcd_de           ,  //LCD 数据输入使能
  8. 8        inout  [23:0    lcd_rgb          ,  //LCD 颜色数据
  9. 9        output           lcd_bl           ,  //LCD 背光控制信号
  10. 10       output           lcd_rst          ,  //LCD 复位信号
  11. 11       output           lcd_pclk         ,  //LCD 采样时钟
  12. 12       //摄像头接口                       
  13. 13       input            cam_pclk         ,  //cmos 数据像素时钟
  14. 14       input            cam_vsync        ,  //cmos 场同步信号
  15. 15       input            cam_href         ,  //cmos 行同步信号
  16. 16       input  [7:0     cam_data         ,  //cmos 数据
  17. 17       output           cam_rst_n        ,  //cmos 复位信号,低电平有效
  18. 18       output           cam_stb          ,  //cmos pwer down
  19. 19       output           cam_scl          ,  //cmos SCCB_SCL线
  20. 20       inout            cam_sda          ,  //cmos SCCB_SDA线
  21. 21       //DDR3接口
  22. 22       input            pad_loop_in      ,  //低位温度补偿输入
  23. 23       input            pad_loop_in_h    ,  //高位温度补偿输入
  24. 24       output           pad_rstn_ch0     ,  //Memory复位
  25. 25       output           pad_ddr_clk_w    ,  //Memory差分时钟正
  26. 26       output           pad_ddr_clkn_w   ,  //Memory差分时钟负
  27. 27       output           pad_csn_ch0      ,  //Memory片选
  28. 28       output [15:0    pad_addr_ch0     ,  //Memory地址总线
  29. 29       inout  [16-1:0  pad_dq_ch0       ,  //数据总线
  30. 30       inout  [16/8-1:0 pad_dqs_ch0     ,  //数据时钟正端
  31. 31       inout  [16/8-1:0 pad_dqsn_ch0    ,  //数据时钟负端
  32. 32       output [16/8-1:0 pad_dm_rdqs_ch0 ,  //数据Mask
  33. 33       output           pad_cke_ch0      ,  //Memory差分时钟使
  34. 34       output           pad_odt_ch0      ,  //On Die Terminati
  35. 35       output           pad_rasn_ch0     ,  //行地址strobe
  36. 36       output           pad_casn_ch0     ,  //列地址strobe
  37. 37       output           pad_wen_ch0      ,  //写使能
  38. 38       output [2:0      pad_ba_ch0       ,  //Bank地址总线
  39. 39       output           pad_loop_out     ,  //低位温度补偿输出
  40. 40       output           pad_loop_out_h      //高位温度补偿输出
  41. 41      );
  42. 42  
  43. 43  //parameter define
  44. 44  parameter SLAVE_ADDR = 7'b1001_000   ;//OV7725的器件地址7'h90
  45. 45  parameter BIT_CTRL   =1'b0          ; //mt9v034的字节地址为8位  0:8位 1:16位
  46. 46  parameter DATA_CTRL  = 1'b1          ;  //mt9v034的数据为8位 0:8位 1:16位
  47. 47  parameter CLK_FREQ   =27'd50_000_000; //i2c_dri模块的驱动时钟频率
  48. 48  parameter I2C_FREQ   =18'd250_000   ;//I2C的SCL时钟频率,不超过400KHz
  49. 49  parameter APP_ADDR_MIN = 28'd0       ; //ddr3读写起始地址,以一个16bit的数据为一个单位
  50. 50  parameter BURST_LENGTH = 8'd64       ; //ddr3读写突发长度,64个128bit的数据
  51. 51
复制代码
程序的第44行,修改了器件的地址。
程序的第46行,添加了参数DATA_CTRL,用以区分一个寄存器地址是写16位数据还是8位数据。
顶层模块中第47至第48行定义了两个变量: CLK_FREQ(i2c_dri模块的驱动时钟频率)和I2C_FREQ(I2C的SCL时钟频率),I2C_FREQ的时钟频率不能超过400KHz,否则有可能导致摄像头配置不成功
  1. 52  //wire define
  2. 53  wire        sys_init_done   ;  //系统初始化完成(DDR3初始化+摄像头初始化)
  3. 54  wire        rst_n           ;  //全局复位
  4. 55  //PLL
  5. 56  wire        clk_50m         ;  //output 50M
  6. 57  wire        clk_100m        ;  //output 100M
  7. 58  wire        clk_locked      ;
  8. 59  //MT9V034
  9. 60  wire        i2c_dri_clk     ;  //I2C操作时钟
  10. 61  wire        i2c_done        ;  //I2C寄存器配置完成信号
  11. 62  wire        i2c_exec        ;  //I2C触发执行信号
  12. 63  wire [7:0  i2c_addr       ;  //I2C要配置的地址
  13. 64  wire [15:0 i2c_wr_data    ;  //I2C要配置的数据
  14. 65  wire        cam_init_done   ;  //摄像头初始化完成
  15. 66  wire        cmos_frame_vsync;  //帧有效信号
  16. 67  wire        cmos_frame_href ;  //行有效信号
  17. 68  wire        cmos_frame_valid;  //数据有效使能信号
  18. 69  wire [15:0 wr_data        ;  //OV7725写入DDR3控制器模块的数据
  19. 70  wire [27:0 ddr3_addr_max  ;  //存入DDR3的最大读写地址
  20. 71  //LCD                       
  21. 72  wire        lcd_clk         ;  //分频产生的LCD采样时钟
  22. 73  wire [10:0 h_disp         ;  //LCD屏水平分辨率
  23. 74  wire [10:0 v_disp         ;  //LCD屏垂直分辨率
  24. 75  wire [15:0 lcd_id         ;  //LCD屏的ID号
  25. 76  wire        out_vsync       ;  //LCD场信号
  26. 77  wire        rdata_req       ;  //读数据请求
  27. 78  //DDR3
  28. 79  wire [15:0 rd_data        ;  //DDR3控制器模块输出的数据
  29. 80  wire        fram_done       ;  //DDR中已经存入一帧画面标志
  30. 81  wire        ddr_init_done   ;  //ddr3初始化完成
  31. 82  
  32. 83  //*****************************************************
  33. 84  //**                    main code
  34. 85  //*****************************************************
  35. 86  
  36. 87  //待时钟锁定后产生结束复位信号
  37. 88  assign  rst_n = sys_rst_n & clk_locked;
  38. 89  
  39. 90  //系统初始化完成:DDR3和摄像头都初始化完成
  40. 91  //避免了在DDR3初始化过程中向里面写入数据
  41. 92  assign  sys_init_done = ddr_init_done & cam_init_done;
  42. 93  
  43. 94  //电源休眠模式选择 0:正常模式 1:电源休眠模式
  44. 95  assign  cam_stb = 1'b0;
  45. 96  
  46. 97  //不对摄像头硬件复位,固定高电平
  47. 98  assign  cam_rst_n = 1'b1;
  48. 99  
  49. 100 //例化PLL IP核
  50. 101 pll_clk  u_pll_clk(
  51. 102      .pll_rst        (~sys_rst_n  ),
  52. 103      .clkin1         (sys_clk     ),
  53. 104      .clkout0        (clk_50m     ),
  54. 105      .clkout1        (clk_100m    ),
  55. 106      .pll_lock       (clk_locked  )
  56. 107 );
  57. 108
  58. 109 //I2C配置模块
  59. 110 i2c_cfg  u_i2c_cfg(
  60. 111      .clk          (i2c_dri_clk  ),
  61. 112      .rst_n        (rst_n        ),
  62. 113      .i2c_done     (i2c_done     ),
  63. 114      .i2c_exec     (i2c_exec     ),
  64. 115      .i2c_addr     (i2c_addr     ),
  65. 116      .i2c_wr_data  (i2c_wr_data  ),
  66. 117      .cfg_done     (cam_init_done)
  67. 118 );
  68. 119
  69. 120 //I2C驱动模块
  70. 121 i2c_dri
  71. 122   #(
  72. 123      .SLAVE_ADDR         (SLAVE_ADDR),    //参数传递
  73. 124      .CLK_FREQ           (CLK_FREQ  ),              
  74. 125      .I2C_FREQ           (I2C_FREQ  )
  75. 126      )
  76. 127   u_i2c_dr(
  77. 128      .clk                (clk_50m        ),
  78. 129      .rst_n              (sys_rst_n      ),
  79. 130      .i2c_exec           (i2c_exec       ),
  80. 131      .bit_ctrl           (BIT_CTRL       ),
  81. 132      .data_ctrl          (DATA_CTRL      ),
  82. 133      .i2c_rh_wl          (0              ), //固定为0,只用到了IIC驱动的写操作   
  83. 134      .i2c_addr           ({8'b0,i2c_addr}),
  84. 135      .i2c_data_w         (i2c_wr_data    ),
  85. 136      .i2c_data_r         (               ),
  86. 137      .i2c_done           (i2c_done       ),
  87. 138      .scl                (cam_scl        ),
  88. 139      .sda                (cam_sda        ),
  89. 140      .dri_clk            (i2c_dri_clk    )  //I2C操作时钟
  90. 141 );
  91. 142
  92. 143 //图像采集顶层模块
  93. 144 cmos_data_top u_cmos_data_top(
  94. 145      .rst_n                 (rst_n & sys_init_done), //系统初始化完成之后再开始采集数据   
  95. 146      .cam_pclk              (cam_pclk            ),              
  96. 147      .cam_vsync             (cam_vsync           ),
  97. 148      .cam_href              (cam_href            ),
  98. 149      .cam_data              (cam_data            ),
  99. 150      .lcd_id                (lcd_id               ),  
  100. 151      .h_disp                (h_disp              ),
  101. 152      .v_disp                (v_disp              ),  
  102. 153      .h_pixel               (                    ),
  103. 154      .v_pixel               (                    ),
  104. 155      .ddr3_addr_max         (ddr3_addr_max       ),   
  105. 156      .cmos_frame_vsync      (cmos_frame_vsync    ),
  106. 157      .cmos_frame_href       (cmos_frame_href     ),
  107. 158      .cmos_frame_valid      (cmos_frame_valid    ), //数据有效使能信号
  108. 159      .cmos_frame_data       (wr_data             )  //有效数据
  109. 160      );
  110. 161
  111. 162 //ddr3
  112. 163 ddr3_top u_ddr3_top(
  113. 164      .refclk_in             (clk_50m        ),
  114. 165      .rst_n                 (rst_n          ),
  115. 166      .app_addr_rd_min       (APP_ADDR_MIN   ),
  116. 167      .app_addr_rd_max       (ddr3_addr_max  ),
  117. 168      .rd_bust_len           (BURST_LENGTH   ),
  118. 169      .app_addr_wr_min       (APP_ADDR_MIN   ),
  119. 170      .app_addr_wr_max       (ddr3_addr_max  ),
  120. 171      .wr_bust_len           (BURST_LENGTH   ),
  121. 172      .ddr3_read_valid       (1'b1            ),
  122. 173      .ddr3_pingpang_en      (1'b1            ),
  123. 174      .wr_clk                (cam_pclk       ),
  124. 175      .rd_clk                (lcd_clk         ),
  125. 176      .datain_valid          (cmos_frame_valid),
  126. 177      .datain                (wr_data        ),
  127. 178      .rdata_req             (rdata_req      ),
  128. 179      .rd_load               (out_vsync      ),
  129. 180      .wr_load               (cmos_frame_vsync),
  130. 181      .fram_done             (fram_done      ),
  131. 182      .dataout               (rd_data        ),
  132. 183      .pll_lock              (pll_lock       ),
  133. 184      .ddr_init_done         (ddr_init_done  ),
  134. 185     .ddrphy_rst_done       (               ),
  135. 186      .pad_loop_in           (pad_loop_in    ),
  136. 187      .pad_loop_in_h         (pad_loop_in_h  ),
  137. 188      .pad_rstn_ch0          (pad_rstn_ch0   ),
  138. 189      .pad_ddr_clk_w         (pad_ddr_clk_w  ),
  139. 190      .pad_ddr_clkn_w        (pad_ddr_clkn_w ),
  140. 191      .pad_csn_ch0           (pad_csn_ch0    ),
  141. 192      .pad_addr_ch0          (pad_addr_ch0   ),
  142. 193      .pad_dq_ch0            (pad_dq_ch0     ),
  143. 194      .pad_dqs_ch0           (pad_dqs_ch0    ),
  144. 195      .pad_dqsn_ch0          (pad_dqsn_ch0   ),
  145. 196      .pad_dm_rdqs_ch0       (pad_dm_rdqs_ch0 ),
  146. 197      .pad_cke_ch0           (pad_cke_ch0    ),
  147. 198      .pad_odt_ch0           (pad_odt_ch0    ),
  148. 199     .pad_rasn_ch0          (pad_rasn_ch0   ),
  149. 200      .pad_casn_ch0          (pad_casn_ch0   ),
  150. 201      .pad_wen_ch0           (pad_wen_ch0    ),
  151. 202      .pad_ba_ch0            (pad_ba_ch0     ),
  152. 203      .pad_loop_out          (pad_loop_out   ),
  153. 204      .pad_loop_out_h        (pad_loop_out_h )
  154. 205      
  155. 206      );  
  156. 207
  157. 208 //LCD驱动显示模块
  158. 209 lcd_rgb_top  u_lcd_rgb_top(
  159. 210      .sys_clk               (clk_50m            ),
  160. 211      .clk_100m              (clk_100m           ),
  161. 212      .sys_rst_n             (rst_n && clk_locked ),
  162. 213      .sys_init_done         (sys_init_done      ),
  163. 214      //lcd接口
  164. 215      .lcd_id                (lcd_id             ), //LCD屏的ID号
  165. 216      .lcd_hs                (lcd_hs             ), //LCD 行同步信号
  166. 217      .lcd_vs                (lcd_vs             ), //LCD 场同步信号
  167. 218      .lcd_de                (lcd_de             ), //LCD 数据输入使能
  168. 219      .lcd_rgb               (lcd_rgb            ), //LCD 颜色数据
  169. 220      .lcd_bl                (lcd_bl             ), //LCD 背光控制信号
  170. 221      .lcd_rst               (lcd_rst            ), //LCD 复位信号
  171. 222      .lcd_pclk              (lcd_pclk           ), //LCD 采样时钟
  172. 223      .lcd_clk               (lcd_clk            ), //LCD 驱动时钟
  173. 224      //用户接口                                 
  174. 225      .h_disp                (h_disp             ), //行分辨率
  175. 226      .v_disp                (v_disp             ), //场分辨率
  176. 227      .pixel_xpos            (                    ),
  177. 228      .pixel_ypos            (                   ),
  178. 229      .out_vsync             (out_vsync          ),
  179. 230      .data_in               (rd_data            ), //rfifo输出数据
  180. 231      .data_req              (rdata_req          )  //请求数据输入
  181. 232      );
  182. 233
  183. 234 endmodule
复制代码
FPGA顶层模块(mt9v034_lcd)例化了以下六个模块: 时钟模块(pll_clk)、 I2C驱动模块(i2c_dri)、I2C配置模块(i2c_cfg)、图像采集顶层模块(cmos_data_top)、DDR3控制顶层模块(ddr3_top)和LCD顶层模块(lcd_rgb_top)。
时钟模块(pll_clk):时钟模块通过调用PLL IP核实现,共输出2个时钟,频率分别为50Mhz时钟和100Mhz时钟。100Mhz时钟作为LCD顶层模块输出时钟的源时钟;50Mhz时钟作为I2C驱动模块、DDR控制模块和LCD顶层模块的驱动时钟。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动MT9V034的两线式接口总线,用户根据该模块提供的用户接口可以很方便的对MT9V034的寄存器进行配置,该模块和“EEPROM 读写实验”章节中用到的I2C 驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM 读写实验”章节。
I2C配置模块(i2c_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出MT9V034的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对MT9V034传感器的初始化。
图像采集顶层模块(cmos_data_top):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成DDR3控制模块的写使能信号和16位写数据信号,完成对MT9V034传感器图像的采集。如果LCD屏的分辨率小于MT9V034的分辨率,还要对MT9V034采集的数据进行裁剪,以匹配LCD屏的分辨率。
DDR3控制顶层模块(ddr3_top):DDR3读写控制器模块负责驱动DDR3片外存储器,缓存图像传感器输出的图像数据。该模块将DDR3 IP核复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关DDR3控制顶层模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
LCD顶层模块(lcd_rgb_top):LCD 顶层模块负责驱动LCD屏的驱动信号的输出,同时为其他模块提供屏体参数、场同步信号和数据请求信号。有关LCD驱动模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
I2C配置模块代码如下所示:
  1. 1  module i2c_cfg(
  2. 2                  input               clk         ,
  3. 3                  input               rst_n       ,
  4. 4                  input               i2c_done    ,
  5. 5                  output  reg         i2c_exec    ,
  6. 6                  output  reg  [7:0   i2c_addr    ,
  7. 7                  output  reg  [15:0  i2c_wr_data ,
  8. 8                  output  reg         cfg_done       //配置寄存器结束
  9. 9                  );
  10. 10 //parameter define   
  11. 11 parameter  DELAY_MAX = 8'hff ;
  12. 12 parameter  ROW_NUM = 16'd480;  //行数
  13. 13 parameter  COL_NUM = 16'd640;  //列数
  14. 14
复制代码
在程序的第11行,定义了一个DELAY_MAX参数,用以保证在上电的时候不会立即配置寄存器,而是等待一段时间后再配置。
在程序的第12和13行定义了2个参数,即本次实验所需要的摄像头的分辨率。
  1. 15 //reg define
  2. 16 reg   [7:0 delay_cnt   ;
  3. 17 reg          delay_done  ;
  4. 18 reg   [3:0  cfg_cnt     ;
  5. 19
  6. 20 //*****************************************************
  7. 21 //**                    main code
  8. 22 //*****************************************************   
  9. 23
  10. 24 always @(posedge clk or negedge rst_n)
  11. 25   begin
  12. 26      if(rst_n==1'b0) begin
  13. 27          delay_cnt <= 1'b0 ;
  14. 28          delay_done <= 1'b0 ;
  15. 29      end
  16. 30      else begin
  17. 31          delay_done <= 1'b0 ;
  18. 32          if(i2c_done) begin
  19. 33              delay_cnt <= 1'b0 ;
  20. 34          end
  21. 35          else if(delay_cnt<DELAY_MAX) begin
  22. 36              delay_cnt <= delay_cnt +1'b1 ;
  23. 37              if(delay_cnt==DELAY_MAX-1'b1) begin
  24. 38                  delay_done <= 1'b1 ;
  25. 39              end
  26. 40          end
  27. 41      end
  28. 42   end           
  29. 43
  30. 44 always @(posedge clk or negedge rst_n)
  31. 45   begin
  32. 46      if(rst_n==1'b0) begin
  33. 47          i2c_exec <= 1'b0;
  34. 48          i2c_addr <= 1'b0;
  35. 49          i2c_wr_data <= 1'b0;
  36. 50          cfg_done <= 1'b0;
  37. 51          cfg_cnt <= 1'b0;
  38. 52      end
  39. 53      else begin
  40. 54          i2c_exec <= 1'b0;
  41. 55          if(cfg_done==1'b0) begin
  42. 56              if(delay_done) begin
  43. 57                  cfg_cnt <= cfg_cnt + 1'b1;
  44. 58                  if(cfg_cnt=='d2) begin
  45. 59                      cfg_done <= 1'b1;
  46. 60                  end
  47. 61                  case(cfg_cnt)
  48. 62                      4'd0 : begin
  49. 63                                 i2c_exec <= 1'b1;
  50. 64                                 i2c_addr <= 8'h03;//03
  51. 65                                 i2c_wr_data <= ROW_NUM;
  52. 66                               end
  53. 67                      4'd1 : begin
  54. 68                                 i2c_exec <= 1'b1;
  55. 69                                 i2c_addr <= 8'h04;
  56. 70                                 i2c_wr_data <= COL_NUM;
  57. 71                               end                                                                                                                    
  58. 72                      default : ;
  59. 73                  endcase         
  60. 74              end
  61. 75          end
  62. 76      end
  63. 77   end                                                   
  64. 78                                       
  65. 79 endmodule
复制代码
在程序的第24至第42行,是用来对延时的计数器进行计数和清零。
在程序的第44至第77行,是对摄像头的行场分辨率进行配置。在第58行是设置需要配置寄存器的个数。
I2C 驱动模块做了以下修改:
  1. 116          st_addr8: begin                         //8位字地址
  2. 117              if(st_done) begin
  3. 118                  if(wr_flag==1'b0)               //读写判断
  4. 119                      if(!data_ctrl)
  5. 120                           next_state = st_data_wr_8;
  6. 121                      else
  7. 122                           next_state = st_data_wr_16;                        
  8. 123                  else
  9. 124                      next_state = st_addr_rd;
  10. 125              end
  11. 126              else begin
  12. 127                  next_state = st_addr8;
  13. 128              end
  14. 129          end
  15. 130          st_data_wr_16: begin                       //写数据(8bit)
  16. 131              if(st_done)
  17. 132                  next_state = st_data_wr_8;
  18. 133              else
  19. 134                  next_state = st_data_wr_16;
  20. 135          end         
  21. 136          st_data_wr_8: begin                       //写数据(8bit)
  22. 137              if(st_done)
  23. 138                  next_state = st_stop;                 
  24. 139              else
  25. 140                  next_state = st_data_wr_8;
  26. 141          end
复制代码
代码116行至129行表示当状态发生跳转并且data_ctrl为1的时候,将状态跳转到st_data_wr_16,否则跳转到其他状态。
代码130行至135行表示当状态发生跳转时,将状态跳转到st_data_wr_8。   
  1. 337              st_data_wr_16: begin                        //写高数据(8 bit)
  2. 338                  case(cnt)                           
  3. 339                      7'd0: begin                     
  4. 340                          sda_out <= data_wr_t[15];     //I2C写高8位数据
  5. 341                          sda_dir <= 1'b1;            
  6. 342                      end                              
  7. 343                      7'd1 : scl <= 1'b1;              
  8. 344                      7'd3 : scl <= 1'b0;              
  9. 345                      7'd4 : sda_out <= data_wr_t[14];  
  10. 346                      7'd5 : scl <= 1'b1;              
  11. 347                      7'd7 : scl <= 1'b0;              
  12. 348                      7'd8 : sda_out <= data_wr_t[13];  
  13. 349                      7'd9 : scl <= 1'b1;              
  14. 350                      7'd11: scl <= 1'b0;              
  15. 351                      7'd12: sda_out <=data_wr_t[12];  
  16. 352                      7'd13: scl <= 1'b1;              
  17. 353                      7'd15: scl <= 1'b0;              
  18. 354                      7'd16: sda_out <= data_wr_t[11];  
  19. 355                      7'd17: scl <= 1'b1;              
  20. 356                      7'd19: scl <= 1'b0;              
  21. 357                      7'd20: sda_out <= data_wr_t[10];  
  22. 358                      7'd21: scl <= 1'b1;              
  23. 359                      7'd23: scl <= 1'b0;              
  24. 360                      7'd24: sda_out <= data_wr_t[9];  
  25. 361                      7'd25: scl <= 1'b1;              
  26. 362                      7'd27: scl <= 1'b0;              
  27. 363                      7'd28: sda_out <= data_wr_t[8];  
  28. 364                      7'd29: scl <= 1'b1;              
  29. 365                      7'd31: scl <= 1'b0;              
  30. 366                      7'd32: begin                     
  31. 367                          sda_dir <= 1'b0;           
  32. 368                          sda_out <= 1'b1;                              
  33. 369                      end                              
  34. 370                      7'd33: scl <= 1'b1;              
  35. 371                      7'd34: begin                     //从机应答
  36. 372                          st_done <= 1'b1;     
  37. 373                          if(sda_in == 1'b1)           //高电平表示未应答
  38. 374                              i2c_ack <= 1'b1;         //拉高应答标志位   
  39. 375                      end         
  40. 376                      7'd35: begin                     
  41. 377                          scl  <= 1'b0;               
  42. 378                          cnt  <= 1'b0;               
  43. 379                      end                              
  44. 380                      default :  ;                    
  45. 381                  endcase                              
  46. 382              end                                                
  47. 383              st_data_wr_8: begin                        //写数据(8 bit)
  48. 384                  case(cnt)                           
  49. 385                      7'd0: begin                     
  50. 386                          sda_out <= data_wr_t[7];     //I2C写低8位数据
  51. 387                          sda_dir <= 1'b1;            
  52. 388                      end                              
  53. 389                      7'd1 : scl <= 1'b1;              
  54. 390                      7'd3 : scl <= 1'b0;              
  55. 391                      7'd4 : sda_out <= data_wr_t[6];  
  56. 392                      7'd5 : scl <= 1'b1;              
  57. 393                      7'd7 : scl <= 1'b0;              
  58. 394                      7'd8 : sda_out <= data_wr_t[5];  
  59. 395                      7'd9 : scl <= 1'b1;              
  60. 396                      7'd11: scl <= 1'b0;              
  61. 397                      7'd12: sda_out <= data_wr_t[4];  
  62. 398                      7'd13: scl <= 1'b1;              
  63. 399                      7'd15: scl <= 1'b0;              
  64. 400                      7'd16: sda_out <= data_wr_t[3];  
  65. 401                      7'd17: scl <= 1'b1;              
  66. 402                      7'd19: scl <= 1'b0;              
  67. 403                      7'd20: sda_out <= data_wr_t[2];  
  68. 404                      7'd21: scl <= 1'b1;              
  69. 405                      7'd23: scl <= 1'b0;              
  70. 406                      7'd24: sda_out <= data_wr_t[1];  
  71. 407                      7'd25: scl <= 1'b1;              
  72. 408                      7'd27: scl <= 1'b0;              
  73. 409                      7'd28: sda_out <= data_wr_t[0];  
  74. 410                      7'd29: scl <= 1'b1;              
  75. 411                      7'd31: scl <= 1'b0;              
  76. 412                      7'd32: begin                     
  77. 413                          sda_dir <= 1'b0;           
  78. 414                          sda_out <= 1'b1;                              
  79. 415                      end                              
  80. 416                      7'd33: scl <= 1'b1;              
  81. 417                      7'd34: begin                     //从机应答
  82. 418                          st_done <= 1'b1;     
  83. 419                          if(sda_in == 1'b1)           //高电平表示未应答
  84. 420                              i2c_ack <= 1'b1;         //拉高应答标志位   
  85. 421                      end         
  86. 422                      7'd35: begin                     
  87. 423                          scl <= 1'b0;               
  88. 424                          cnt  <= 1'b0;               
  89. 425                      end                              
  90. 426                      default :  ;                    
  91. 427                  endcase                              
  92. 428              end
复制代码
代码337行至382行,表示写入数据的高8位。
代码383行至428行,表示写入数据的低8位。
图像采集顶层模块(cmos_data_top)例化了以下两个模块:图像采集模块(cmos_capture_raw_gray)和图像裁剪模块(cmos_tailor)。有关图像采集顶层模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
图像采集模块(cmos_capture_raw_gray)为其他模块提供摄像头8bit输入数据和数据使能以及摄像头稳定后的行场信号。图像裁剪模块(cmos_tailor)只有在LCD的器件ID为16’h4342时起作用,即摄像头的分辨率大于LCD屏的分辨率,起到裁剪图像数据,使图像的有效数据达到匹配LCD屏的尺寸。有关图像裁剪模块的详细介绍请大家参考“OV7725摄像头RGB-LCD 显示实验”章节。
图像采集模块的代码如下:
  1. 1   module cmos_capture_raw_gray
  2. 2   #(
  3. 3        parameter  CMOS_FRAME_WAITCNT = 4'd10  //等待数据稳定所需要的帧数
  4. 4                                                               
  5. 5   )
  6. 6   (
  7. 7        //global clock
  8. 8        input      clk_cmos        , //锁相环分频时钟
  9. 9        input      rst_n           , //复位信号,低有效
  10. 10       //CMOS Sensor Interface
  11. 11       input      cmos_pclk       , //摄像头输入时钟
  12. 12       output     cmos_xclk       , //摄像头驱动时钟
  13. 13       input      cmos_vsync      , //摄像头场信号
  14. 14       input      cmos_href       , //摄像头行信号
  15. 15       input [7:0 cmos_data       , //摄像头数据   
  16. 16       //CMOS SYNC Data output
  17. 17       output     cmos_frame_vsync, //摄像头场有效信号
  18. 18       output     cmos_frame_href , //摄像头行有效信号
  19. 19       output[15:0wr_data        , //摄像头有效数据   
  20. 20       output     cmos_frame_clken, //摄像头数据有效使能   
  21. 21       //user interface
  22. 22       output[7:0 cmos_fps_rate     //摄像头帧率
  23. 23  );
  24. 24  
  25. 25  //parameter define   
  26. 26  localparam  DELAY_TOP = 2 * 24_000000;  //2s delay
  27. 27  
  28. 28  //reg define
  29. 29  reg [27:0 delay_cnt      ;
  30. 30  reg         frame_sync_flag;
  31. 31  reg [3:0  cmos_fps_cnt   ;
  32. 32  reg [8:0  cmos_fps_cnt2  ;
  33. 33  reg [7:0  cmos_fps_rate  ;
  34. 34  reg [1:0   cmos_vsync_r, cmos_href_r ;
  35. 35  reg [7:0   cmos_data_r0, cmos_data_r1;
  36. 36  
  37. 37  //wire define
  38. 38  wire        cmos_vsync_end ;
  39. 39  wire        delay_2s       ;
  40. 40  wire [7:0 cmos_frame_data;
  41. 41  
  42. 42  //*****************************************************
  43. 43  //**                    main code
  44. 44  //*****************************************************   
  45. 45  
  46. 46  assign  cmos_vsync_end      =   (cmos_vsync_r[1 & ~cmos_vsync_r[0]) ? 1'b1 : 1'b0;
  47. 47  assign  cmos_xclk = clk_cmos;   //24MHzCMOS XCLK output
  48. 48  assign  cmos_frame_clken = frame_sync_flag  ? cmos_href_r[1 : 1'b0;
  49. 49  assign  cmos_frame_vsync = frame_sync_flag  ? cmos_vsync_r[1 : 1'b0;//DFF 2clocks
  50. 50  assign  cmos_frame_href  = frame_sync_flag ? cmos_href_r[1 : 1'b0;  //DFF 2 clocks
  51. 51  assign  cmos_frame_data  = frame_sync_flag  ? cmos_data_r1 : 8'd0;   //DFF 2 clocks
  52. 52  assign  delay_2s = (delay_cnt == DELAY_TOP - 1'b1) ? 1'b1 : 1'b0;
  53. 53  assign  wr_data = {cmos_frame_data[7:3],cmos_frame_data[7:2],cmos_frame_data[7:3]};
  54. 54
复制代码
在程序的第53行实现了8位数据转16位数据的功能,这里将8位的灰度数据按照高位赋值的方式将数据按照RGB565的格式分别赋给各个颜色分量。需要注意的是摄像头的图像数据是在像素时钟(cam_pclk)下输出的,因此摄像头的图像数据必须使用像素钟来采集,否则会造成数据采集错误。
  1. 55  always@(posedge cmos_pclk or negedge rst_n)begin
  2. 56       if(!rst_n)
  3. 57           begin
  4. 58           cmos_vsync_r <= 0;
  5. 59           cmos_href_r <= 0;
  6. 60           {cmos_data_r1, cmos_data_r0} <= 0;
  7. 61           end
  8. 62       else
  9. 63           begin
  10. 64           cmos_vsync_r <= {cmos_vsync_r[0], cmos_vsync};
  11. 65           cmos_href_r <= {cmos_href_r[0], cmos_href};
  12. 66           {cmos_data_r1, cmos_data_r0} <= {cmos_data_r0, cmos_data};
  13. 67           end
  14. 68  end
  15. 69  
  16. 70  //Wait for Sensor outputData valid 10 Frame of OmniVision
  17. 71  always@(posedge cmos_pclk or negedge rst_n)begin
  18. 72       if(!rst_n)
  19. 73           cmos_fps_cnt <= 0;
  20. 74       else    //Wait until cmos init complete
  21. 75           begin
  22. 76           if(cmos_fps_cnt < CMOS_FRAME_WAITCNT)   
  23. 77               cmos_fps_cnt <= cmos_vsync_end ? cmos_fps_cnt + 1'b1 : cmos_fps_cnt;
  24. 78           else
  25. 79               cmos_fps_cnt <= CMOS_FRAME_WAITCNT;
  26. 80           end
  27. 81  end
  28. 82  
  29. 83  //Come ture framesynchronization to ignore error frame or has not capture when vsync begin
  30. 84  always@(posedge cmos_pclk or negedge rst_n)begin
  31. 85       if(!rst_n)
  32. 86           frame_sync_flag <= 0;
  33. 87       else if(cmos_fps_cnt == CMOS_FRAME_WAITCNT && cmos_vsync_end == 1)
  34. 88           frame_sync_flag <= 1;
  35. 89       else
  36. 90           frame_sync_flag <= frame_sync_flag;
  37. 91  end
  38. 92  
  39. 93  //Delay 2s for cmos fpscounter
  40. 94  always@(posedge cmos_pclk or negedge rst_n)begin
  41. 95       if(!rst_n)
  42. 96           delay_cnt <= 0;
  43. 97       else if(delay_cnt < DELAY_TOP - 1'b1)
  44. 98           delay_cnt <= delay_cnt + 1'b1;
  45. 99       else
  46. 100          delay_cnt <= 0;
  47. 101 end
  48. 102
  49. 103 //cmos image output ratecounter
  50. 104 always@(posedge cmos_pclk or negedge rst_n)begin
  51. 105      if(!rst_n)
  52. 106          begin
  53. 107          cmos_fps_cnt2 <= 0;
  54. 108          cmos_fps_rate <= 0;
  55. 109          end
  56. 110      else if(delay_2s ==1'b0)   //time is not reached
  57. 111          begin
  58. 112          cmos_fps_cnt2 <= cmos_vsync_end ? cmos_fps_cnt2 + 1'b1 : cmos_fps_cnt2;
  59. 113          cmos_fps_rate <= cmos_fps_rate;
  60. 114          end
  61. 115      else    //time up
  62. 116          begin
  63. 117          cmos_fps_cnt2 <= 0;
  64. 118          cmos_fps_rate <= cmos_fps_cnt2[8:1];    //divide by 2
  65. 119          end
  66. 120 end
  67. 121
  68. 122 endmodule
复制代码
CMOS 图像采集模块第3行定义了参数CMOS_FRAME_WAITCNT(寄存器数据稳定等待的帧个数),这里设置等待帧是为了保证摄像头输出稳定后才采样数据。这里采集场同步信号的上升沿来统计帧数,计数器计数超过10次之后产生数据有效的标志(frame_sync_flag),开始采集图像。
在程序的第94行至101行,是对2s的时间进行计数。
在程序的第103行至120行,是对摄像头的帧率进行计数。在110行至119行,当2s的时间未到且当场信号的下降沿到来时,对帧率计数器进行累加,当 2s 的时间到来时,对帧率计数器进行清零,把帧率计数器除以2的值赋给帧率寄存器。
我们在前面说过,本章实验程序设计和“OV7725摄像头RGB-LCD显示实验”相比,我们只是把外设OV7725模块替换成了MT9V034模块,替换了图像采集模块和I2C配置模块,修改了I2C驱动模块,其余模块基本相同。本章节主要介绍了I2C配置模块、图像采集模块和I2C驱动模块,而其它相同模块的程序设计详情请大家参考“OV7725摄像头RGB-LCD显示实验”章节。

1.5 下载验证
首先将MT9V034摄像头插入开发板上的摄像头扩展接口(注意摄像头镜头朝外);将FPC排线一端与正点原子的7寸RGB模块上的J1接口连接,另一端与ATK-DFPGL22G开发板上的RGB_LCD接口连接;如图 43.5.1和图 43.5.2所示。连接时,先掀开FPC连接器上的黑色翻盖,将FPC排线蓝色面朝上插入连接器,最后将黑色翻盖压下以固定FPC排线。
连接实物图如下图所示:
image027.png
图 43.5.1 ATK-7’ RGB-LCD模块FPC连接器
image029.png
图 43.5.2 开发板FPC连接器
最后将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,验证MT9V034摄像头RGB-LCD实时显示功能。下载完成后观察显示器的显示图像如下图所示,说明MT9V034摄像头LCD显示程序下载验证成功。
image031.jpg
图 43.5.3 RGB-LCD实时显示图像
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 17:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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