ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FPGA图像采集与显示:OV7725摄像头到TFT-LCD的完整工程实现

FPGA图像采集与显示:OV7725摄像头到TFT-LCD的完整工程实现 简介本资源是一套完整的FPGA图像采集与显示实验工程面向数字电路、嵌入式图像处理方向的本科高年级学生及FPGA初学者解决OV7725摄像头原始图像采集、RGB565格式转换、SDRAM缓存及640×480分辨率TFT-LCD实时显示等核心问题。工程基于Cyclone IV E系列EP4CE10F17C8器件使用Quartus 18.0开发含366个文件主体为104个.cdb编译数据库、102个.hdb层次化数据库和20个.vVerilog源码涵盖i2c_ov7725_rgb565_cfg、sdram_top、cmos_capture_data等关键模块另有.bak备份文件与.qsf约束文件保障可复现性。压缩包大小8.66MB结构清晰、模块解耦明确附带完整顶层接口定义与参数化配置如I2C频率250kHz、CMOS像素时钟同步逻辑。目前已有563人学习下载读者可直接编译下载至开发板运行快速掌握CMOS摄像头驱动、SDRAM视频缓存、LCD时序控制三大FPGA图像系统关键技术。 我先把话放前面如果你正准备在FPGA上做一块OV7725摄像头采集、然后通过Verilog把画面推到640x480 RGB TFT-LCD屏上的工程这篇文章就是给你写的。你拿到的那个工程文件我先不评价好坏我只告诉你这个模块链路里真正会卡住人的地方在哪、为什么卡、以及怎么绕过去。这个项目看着简单——摄像头进来FPGA搬个砖屏上出图。但真正做过的人都知道从SCCB寄存器配置到像素时钟对齐从行场同步消隐到FIFO读写时序每一步都有能让你卡三天的问题。下面我按实际调试顺序把这个工程的完整技术链路拆开讲从硬件连接讲到SignalTap排错全部是实操里的经验。1. 这套方案的整体面貌一条能把“图像采集显示驱动”整个闭环走通的绝佳练习路径1.1 工程目标与核心模块划分这个工程要实现的最终效果是OV7725摄像头模组上电后通过SCCB总线完成寄存器初始化摄像头开始输出640x480分辨率的RGB565图像数据FPGA内部完成数据采集、缓存、时序同步最终在RGB TFT-LCD屏幕上实时显示摄像头画面。模块划分是典型的“一采一存一显”三段式结构跟很多工业级图像采集项目同构摄像头上电初始化模块通过SCCB协议本质是类似I2C的两线串行总线向OV7725的寄存器写入配置参数设定输出分辨率、像素时钟、数据格式、增益曝光等。CMOS图像数据采集模块根据OV7725输出的PCLK、VSYNC、HREF以及8位并行数据D[7:0]恢复出完整的像素信息并转换成16位RGB565数据流。图像缓存模块因为摄像头采集速率与LCD刷新率不同步需要一个缓冲区域完成跨时钟域数据搬运。这个工程用的是片上双端口RAM加FIFO组合方案后面我会展开讲为什么这样设计。LCD显示驱动模块按照TFT-LCD的数据手册时序要求生成像素时钟、行同步、场同步、数据使能等信号把缓存中的RGB数据按行列顺序刷到屏幕上。锁相环与时钟管理模块通过Quartus里的PLL IP核从开发板晶振产生摄像头工作时钟、FPGA逻辑时钟、LCD像素时钟等多路时钟。从工程结构上看这套代码就是FPGA图像处理领域的一副骨架。你把它吃透了后面什么色彩空间转换、灰度化、边缘检测、中值滤波无非是在这条数据通路上插入一个个处理模块而已。1.2 为什么选640x480这个分辨率组合很多人一开始不理解为什么这个工程非要用640x480的摄像头输出配合640x480的RGB TFT-LCD屏用720P摄像头输出裁一块区域到屏上显示行不行答案是行但对新手极不友好。关键是像素时钟与帧率匹配。OV7725在640x480分辨率下可以输出VGA时序场频约60fpsPCLK像素时钟大约24MHz而640x480分辨率的RGB LCD屏其典型像素时钟也在25MHz左右具体以屏的手册为准。两者处在同一数量级这意味着FPGA不需要做大量像素缓存来匹配极端的速率差行场同步信号的逻辑关系也很清晰非常适合作为入门练习。如果换到720P甚至1080P的摄像头输出你会立刻遇到两个问题一是PCLK频率翻倍FIFO读写带宽压力增大二是分辨率大于屏的分辨率必须做缩放或裁剪这就要引入行缓存甚至帧缓存资源占用指数级上升。很多新手第一步就栽在这里——不是代码不会写是整个方案复杂度没控制好。1.3 这套方案适合谁以及后续的扩展方向我个人的判断是这个工程非常适合以下几类人——FPGA初学者想用真实硬件验证Verilog语法、时序约束、状态机设计的实际项目而不是只做流水灯。准备投嵌入式/FPGA图像方向岗位的同学这个项目涵盖SCCB/I2C通信、像素时序恢复、跨时钟域处理、显示驱动面试时能讲清楚这套链路含金量比单纯背八股文高得多。想快速做出“摄像头看到什么屏幕就显示什么”效果的DIY玩家整套方案元件少、接线简单核心代码模块化后一个周末就能跑通。扩展方向也很清晰加一个阈值判断就能做运动检测加一个FIFO做灰度直方图统计把双端口RAM换成SDRAM控制器就能跑更大的分辨率。可以说这套工程是后续所有图像类FPGA项目的地基。2. 硬件连接与引脚约束翻车率最高的环节信号完整性和电平匹配必须提前确认2.1 OV7725模组接口逐一拆解先看摄像头模组这边。市面上绝大多数OV7725模块都是DVP接口引出的信号基本一致你需要关注的引脚有信号名方向功能说明VCC电源通常3.3V供电但请注意OV7725核心可能需要1.8V内部LDO多数模组已集成GND地共地必须与FPGA开发板共地SCL/SIO_C输入SCCB时钟线由FPGA产生频率通常几百kHzSDA/SIO_D双向SCCB数据线必须接上拉电阻通常4.7k左右VSYNC输出场同步信号帧开始/结束的标志HREF输出行参考信号高电平期间D[7:0]上的数据有效PCLK输出像素时钟每个上升沿对应一个像素数据D[7:0]输出8位并行像素数据RGB565格式下分两次传输接着是TFT-LCD这边。RGB接口屏的信号要区分清楚一般包括信号名方向功能说明R[4:0]输出到屏红色分量5位G[5:0]输出到屏绿色分量6位B[4:0]输出到屏蓝色分量5位HSYNC输出到屏行同步脉冲VSYNC输出到屏场同步脉冲DE输出到屏数据使能高电平期间RGB数据有效PCLK输出到屏像素时钟背光控制输出到屏控制背光开关和亮度需要注意有些LCD屏叫法不同比如DE也叫DEN或Data EnablePCLK也叫DOTCLK或CLK拿到屏后先看数据手册别凭老经验硬套。2.2 引脚分配策略与I/O标准设置引脚分配这一步很多人直接在Quartus Pin Planner里随便点结果不是信号干扰就是时序不满足。我给你几个实际工程中总结出来的原则摄像头信号线成组绑定尽量走同一个Bank。D[7:0]、PCLK、VSYNC、HREF、SCL、SDA这些信号最好分配在FPGA的同一个I/O Bank而且选在相邻的引脚。原因很简单DVP接口是并行同步传输引脚间走线长度差异如果过大PCLK沿到达时数据线还没稳定就会产生建立/保持时间违规。PCLK引脚选用专用时钟引脚。如果FPGA支持把摄像头的PCLK接入MRCC或SRCC专用时钟输入引脚这样PCLK可以走全局时钟网络保证扇出到所有寄存器的时钟偏斜最小。有些开发板会把摄像头PCLK留在普通IO上不是不行但你要在时序约束上给足余量。LCD像素时钟同样优先专用时钟引脚。原因同上LCD PCLK在25MHz左右虽然不是超高频但全局时钟网络的信号质量对屏显稳定性影响很大。SCCB的SCL和SDA要选带内部上拉的引脚或外部上拉。OV7725的SCCB是开漏结构FPGA侧如果不是真正的开漏输出模式就需要外接上拉电阻。很多开发板摄像头的SDA已经加好上拉但有些精简板没有记得看原理图。2.3 电气连接上最容易忽略的几个细节第一个细节是摄像头模组的供电电流。OV7725正常工作电流在50mA左右有红外补光灯的版本可能更高。如果你从FPGA开发板的3.3V LDO上取电而那块LDO还要供其他模块有可能出现电压跌落表现为图像有横纹或随机白点。建议有条件就单独用一路低噪声LDO供电或者在摄像头电源引脚附近加一颗10uF钽电容加0.1uF陶瓷电容。第二个细节是SCCB上拉电阻的取值。有些开发板的上拉电阻焊了10k甚至更小如果总线频率跑到了400kHz以上SCL的上升沿会变缓导致摄像头偶发配置失败。我一般会把SCCB时钟设在200kHz到400kHz之间上拉4.7k最稳。第三个细节是共地与参考地。摄像头模组、LCD屏、FPGA三者必须共地。LCD屏的LCD_GND和信号GND不要分开否则逻辑电平参考点不一致屏上会出现闪烁的噪点。3. OV7725初始化配置SCCB读写时序和寄存器清单这是整个工程的第一道坎3.1 SCCB协议与I2C的异同OV7725使用的SCCB协议Serial Camera Control Bus本质上就是I2C的超集完全兼容I2C的读操作但在写操作上只支持连续写。也就是说你可以像操作I2C从机一样发送起始位、从机地址、寄存器地址、数据、停止位。与I2C显著不同的地方在于SCCB的从机地址是8位格式OV7725的写地址是0x42读地址是0x437位地址0x21左移一位加上读写位。如果你按I2C的7位地址0x21去发很多FPGA代码会直接把读写位放在最后确实能工作但容易出问题的是有些例程里地址搞混导致寄存器写不进去。SCCB时序的几个关键点SCL空闲时为高SDA在SCL高电平期间不允许变化起始/停止除外。数据在SCL低电平期间变化SCL上升沿采样一次传输8位后面跟一个应答位。起始条件SCL保持高时SDA由高变低。停止条件SCL保持高时SDA由低变高。我在Verilog里通常用一个三段式状态机实现SCCB主机分为IDLE、START、ADDR、REG_ADDR、DATA、STOP等状态。关键是状态机里每个位都要有足够的延时确保SCL半周期不低于2.5us对应200kHz的SCL频率。不要试图跑太快OV7725的SCCB不是为高速设计的。3.2 核心寄存器配置清单从分辨率到输出格式OV7725的寄存器多达190多个但实际初始化只需要配置其中一小部分。我给出一个经过反复验证的最小配置集合寄存器地址均为16进制寄存器地址寄存器名称配置值说明0x12COM70x06使能RGB输出设为VGA时序0x11CLKRC0x01内部PLL关闭使用外部时钟直接分频PCLK 输入时钟/20x0CCOM30x00关闭自动窗口默认窗口使能0x0DCOM40x40PLL倍频设为10x17HSTART0x23水平起始位置高8位配合HREF0x18HSIZE0xA0水平宽度低8位640像素0x19VSTART0x07垂直起始位置0x1AVSIZE0xF0垂直高度低8位480行0x29HOUTSIZE0xA0输出水平宽度高8位6400x2AHOUTSIZE0x00输出水平宽度低4位配合上面0x2BVOUTSIZE0xF0输出垂直高度4800x2CHREF0x00HREF控制字参考数据手册0x0FCOM90x4FAGC增益上限最大到16倍0x13COM80xFF使能AGC、AWB、AEC开启自动曝光0x14COM90x2F自动增益控制最大值0x15COM100x00数据格式相关保证RGB565输出0x4FMTX10x80颜色矩阵系数影响色彩饱和度0x50MTX20x80颜色矩阵系数0x51MTX30x00颜色矩阵系数0x52MTX40x22颜色矩阵系数0x53MTX50x5E颜色矩阵系数0x54MTX60x80颜色矩阵系数0x58MTXS0x9E颜色矩阵系数和符号0x3DCOM120x03使能HREF输出设置HSYNC极性0x3ECOM130x00关闭VSYNC翻转0x40COM150xC0RGB565输出格式0xC0对应RGB5650x41COM160x381/2分频输出使能输出像素数据0x42COM170x00关闭测试图案0x43COM180x00关闭测试图案这里有个重要逻辑要记住COM7配置为RGB模式之后还要把COM15设置为0xC0才能让D[7:0]按RGB565格式输出。0xC0在COM15里的含义是输出格式为RGB565且YUV色彩空间关闭。如果你忘了设COM15摄像头的输出很可能还是YUV422格式后面解码出来的画面就是色彩完全错乱的。3.3 我踩过的一个经典配置坑PCLK频率和曝光联动刚开始调试这个工程时我犯过一个特别典型的错误——把CLKRC寄存器设得很大认为像素时钟越高帧率越高。结果画面出来之后亮度和对比度都异常暗部的噪点非常明显。原因是这样的OV7725在640x480分辨率下默认的像素时钟频率由输入时钟经过CLKRC分频得到。如果PCLK太高一行时间变短内部自动曝光算法为了匹配当前亮度会强制降低增益信噪比图像就会出现明显的暗电流噪声。后来我把CLKRC设为0x01即PCLK 输入时钟24MHz/ 2 12MHz图像质量明显改善。这里也提醒大家不是所有摄像头输出频率越高越好对DVP并口来说降低PCLK意味着FPGA侧时序余量更充足信号误采样的概率更小。工程上先让屏幕稳定出图再慢慢提高帧率是更稳妥的做法。3.4 如何验证SCCB初始化是否成功很多新手问摄像头没有输出图像怎么判断是初始化失败还是采集问题第一道验证方法是回读寄存器。SCCB支持读操作初始化完成后把0x12COM7读回来如果读回的值是0x06附近实际读回的是寄存器当前的输出状态说明总线通了配置写入了。如果读回0xFF或者时序异常值大概率是SCCB时序问题或地址错误。第二道验证方法是捕捉VSYNC和PCLK。用逻辑分析仪或者直接在FPGA里写一个计数器统计1秒内VSYNC到来的次数。OV7725在VGA模式下配置成功后VSYNC频率应该在60fps左右。如果VSYNC完全不来或者频率非常不稳定多半是初始化后摄像头没有正常进入流模式。第三道更直接的验证是利用OV7725内置测试图案。把寄存器0x42COM17的bit7置1摄像头会输出一个内置的彩色竖条纹测试图不需要外部场景。如果初始化和采集链路是通的即使光线很暗、镜头盖没摘屏幕上也能看到清晰的彩条。这个技巧在区分“摄像头没配置好”和“后续图像处理有bug”时非常好用。4. 图像采集模块从PCLK流中恢复640x480像素矩阵行场同步必须处理干净4.1 DVP输出时序的完整解读OV7725的DVP接口时序是这样的一帧图像以VSYNC低脉冲开始也可以配置为高脉冲VSYNC拉低后经过一段消隐区然后是一行一行的HREF高电平输出。HREF高电平期间每个PCLK上升沿对应一个像素的高字节或低字节PCLK和HREF的时序关系在数据手册中有严格定义。以RGB565输出为例每个像素的数据是16位通过8位总线分两次传。第一个PCLK上升沿传高字节R[4:0] G[5:3]第二个PCLK上升沿传低字节G[2:0] B[4:0]。如果你的状态机只采一个PCLK边沿拼出来的数据错位是必然的。所以采集模块的核心逻辑是在HREF为高时建立一个像素计数器计数到偶数把两个8位拼成16位RGB565计数到奇数则丢弃或缓存。拼好后的RGB数据再写入FIFO。这里细节容易出错的是HREF和PCLK之间的建立时间。数据手册给出的规格一般在几十纳秒级别而FPGA内部逻辑采样是有延迟的。最稳妥的做法是先用PCLK采样HREF打两拍得到同步后的HREF和高有效窗口再用这个同步后的HREF去框选数据。绝对不要直接用原始的HREF去使能写FIFO否则亚稳态会让图像边缘出现随机像素。4.2 采集状态机的设计思路我常用的采集模块状态机大致包含这几个状态IDLE等待VSYNC有效进入帧头处理。FRAME_HEADVSYNC无效后等待HREF拉高然后进入LINE_CAPTURE。LINE_CAPTUREHREF高期间每个PCLK上升沿采集一个字节两个字节拼成RGB565写入FIFO。一行结束后进入LINE_BLANK。LINE_BLANK等待下一行HREF或者等待VSYNC到来表示一帧结束。这个状态机本身不复杂但有个细节HREF和VSYNC都是异步信号每个都必须打两拍再使用。我以前跳过这个步骤结果在FPGA板上偶发出现图像上半部分正常、下半部分错位十几行的情况排查了大半天最后怀疑是亚稳态导致VSYNC的同步沿和HREF的行计数对不上。打两拍之后彻底消失。4.3 行同步与场同步的重新对齐策略摄像头输出的时序和最终LCD显示需要的时序并不是天然对称的。摄像头那边有HREF来标定行的有效数据但LCD这边往往是用DE或HSYNC/VSYNC组合来标定。而且两边的消隐时间和有效像素宽度并不一致像素总数也不同。因此你不能“摄像头来什么就往LCD刷什么”必须先把数据按帧缓存下来然后按LCD的时序重新读取。在缓存架构上我推荐的做法是摄像头写入侧以帧同步信号作为写起始标志LCD读取侧以自身的同步时序作为读起始标志中间通过FIFO水位控制防止空读或覆盖。具体来说当一帧开始写入FIFO时记录写指针LCD端每帧读取时从FIFO读出一整帧的数据帧结束后复位读指针。这里有一个反压问题如果LCD刷新率比摄像头帧率快FIFO会瞬时读空反过来摄像头写入快于LCD读取FIFO会溢出。处理方法是只送新帧一旦新帧的帧头到来就清空FIFO重新开始保证显示总是最新一帧图像被覆盖的旧帧直接丢弃。5. 缓存方案选型640x480分辨率为什么不需要SDRAM片上FIFO就够了5.1 资源账先算清楚一帧图像有多大、带宽多大640x480分辨率RGB565格式每像素16位2字节。一帧原始数据量是640 * 480 * 2 614400字节换算一下大约600KB。600KB存储什么概念以内嵌存储块资源较多的Cyclone IV为例单块M9K存储块是9Kb约1.1KB要存600KB需要大约550块M9K。绝大部分主流FPGA比如Cyclone IV E系列的EP4CE10片上也只有不到50块M9K显然不可能用片上资源存完整一帧。这也是很多人一上来就想到SDRAM的原因。但是——你仔细想一下真的需要存完整一帧吗摄像头的帧率是60fpsLCD的刷新率也是60fps左右两者的速率基本匹配而且是一对一的实时显示场景。在这种情况下你不需要暂存完整帧再做后处理你只需要一个行缓存甚至一个小的FIFO缓冲来匹配瞬时速率差异就可以了。这里的关键在于摄像头逐行输出LCD也逐行刷新如果两端行速率接近跨时钟域缓冲只需要覆盖一行的数据传输时间差。640x480一行有640个像素加上消隐区实际上每行大约800个PCLK周期。如果两端速率差在10%以内一个深度为1024的FIFO就足够应对一整行的摆动。这是这个项目能不用SDRAM的核心逻辑。5.2 片上双端口RAM与FIFO的组合方案实际工程里我采用的方案是双端口RAM做行缓存 FIFO做跨时钟域缓冲。具体结构是摄像头的像素数据首先按行写入一个行缓存RAM宽度16位深度1024。每写满一行产生一个行完成信号。LCD读取侧每需要一行数据时从行缓存中去读。由于LCD的一行也是640像素在行消隐期内完成一行的搬运绰绰有余。这个行缓存本身是双端口RAM写时钟是摄像头PCLK读时钟是LCD像素时钟PCLK_LCD。两端时钟不同步正好通过双端口RAM天然解决。如果一个行缓存不够比如LCD时序和摄像头行消隐周期差异大可以再加一个FIFO做深度缓冲。不过就我测试来看640x48060fps对60fps刷新率的LCD屏一个行缓存加一个小FIFO足够稳定。5.3 缓存深度的量化计算这里我把计算过程给出来方便你根据自己屏的参数改。假设OV7725实际输出字段每行总像素数 640有效 144水平消隐≈ 784像素每帧总行数 480有效 45垂直消隐≈ 525行。PCLK 12MHz时每行时间 784 / 12MHz ≈ 65.3us。LCD侧假设像素时钟25MHz每行总像素 800其中有效640消隐160每行时间 800 / 25MHz 32us。垂直方向每帧总计525行刷新率 25MHz / (800 * 525) ≈ 59.5fps。两边帧率都在60fps附近但行时间相差约2倍。LCD刷一行只要32us摄像头产出一行要65.3us这意味着即使FIFO完全空了LCD也必须等待下一行摄头的行数据。为了不出现画面撕裂或缺失FIFO至少要缓存当前正在传输的那一行数据。因此FIFO深度取一行像素数640个16位数据是底线取1024最稳妥因为还应对边界毛刺。至于行缓存容量同样是640个16位数据算下来每模块的存储开销只有1024*16 16Kb两个模块加起来32Kb在M9K资源里只占了4块左右完全在片上资源允许范围内。这就是为什么640x480这个分辨率不用SDRAM也能跑得很稳的原因。5.4 什么时候才必须上SDRAM如果你后面要做这些事那就老老实实上SDRAM或者DDR摄像头输出分辨率大于LCD分辨率需要整帧缩放——因为缩放算法必须访问整帧的多个行数据。要做多帧叠加、背景建模、运动检测等帧间算法——需要保存历史帧。摄像头帧率远高于LCD刷新率且你不想丢帧——必须用帧缓存来平滑。要做慢动作回放、冻结帧等特殊效果——需要存储多帧。否则在“一进一出、实时显示”这个场景下故意引入SDRAM控制器只会增加系统复杂度和调试难度没有任何好处。6. TFT-LCD驱动与像素时钟对齐RGB接口不等于随便刷时序参数可以抄作业6.1 RGB接口与8080接口的区分很多学生党一见到TFT-LCD就以为是原子哥那种FSMC驱动的8080并口屏拿出来就是LCD_CS、LCD_RS、LCD_WR那套信号。但RGB接口的TFT-LCD完全是另一回事。RGB接口屏的信号组合是像素时钟DOTCLK/PCLK、行同步HSYNC、场同步VSYNC、数据使能DE以及RGB各分量数据线。它没有读写控制线也不存在“写寄存器”这种操作。你只要持续不断地按屏的时序要求刷新RGB数据屏幕就持续显示画面一旦不给数据屏幕可能白屏或黑屏取决于屏的配置。8080接口屏适合单片机而RGB接口屏更适合FPGA——因为FPGA可以轻松产生精确到像素周期的时序信号而单片机上产生这类时序需要频繁操作IO效率很低。这也是这个工程选FPGA的意义所在。6.2 一组可以直接使用的640x480 LCD时序参数不同厂家的屏时序参数略有差异但640x48060Hz的RGB接口屏基本遵循VESA标准我贴一组实际工程中验证可用的时序参考参数数值像素时钟25.175MHz可用25MHz替代水平有效像素640水平前沿 HFP16水平同步脉冲 HSPW96水平后沿 HBP48水平总周期800垂直有效行480垂直前沿 VFP10垂直同步脉冲 VSPW2垂直后沿 VBP33垂直总周期525注意HFP、HSPW、HBP这些值你需要按屏的数据手册来核对。有些屏的HSYNC是负极性有效有些是正极性极性反了最常见的表现是画面水平偏移或滚动。生成这套时序的Verilog逻辑本质是一个行计数器加一个场计数器。行计数器在0~799之间循环设定HSYNC在某个区间拉低场计数器在0~524之间循环设定VSYNC在某个区间拉低DE信号在水平有效区HSPWHBP到HSPWHBP640之间和垂直有效区VSPWVBP到VSPWVBP480之间同时为高时拉高。6.3 像素时钟从哪里来RGB屏的像素时钟不能随便给它决定了屏的刷新率。用开发板的50MHz时钟直接驱动行计数器也可以但算一下像素时钟50MHz、每行800像素时行频62.5kHz帧频约119fps远超过屏的手册规格很多屏会直接花屏或白屏。正确的做法是用Quartus里的PLL IP核输入50MHz或开发板实际频率输出25MHz作为LCD的像素时钟。同时PLL可以输出一路12MHz或24MHz作为摄像头的输入时钟。注意PLL的locked信号要接到复位逻辑中PLL锁定后再释放复位否则摄像头初始化时时钟还没稳定SCCB写寄存器就会出现偶发失败。我把PLL参数举个例子如果开发板晶振是50MHz设定PLL输出c0 25MHz给LCDc1 24MHz给OV7725输入c2 50MHz给FPGA逻辑主时钟。这样整条数据链路都在一个可靠的时钟网络下工作。6.4 行场时序对齐解决画面左右偏移和上下跳动时序对齐是整个显示驱动最容易出问题的地方。常见的现象是画面内容正常但整个画面向左偏移了几个像素或者向下偏移了几行。本质原因是你的DE信号有效区间和摄像头数据的行列位置没有对应上。你用HSPWHBP作为行有效起点但摄像头那边HREF拉高时对应的像素并不一定恰好是LCD行的第0个像素两者相差一个固定的偏移量甚至可能是一行就会造成画面平移。解决方法有两个一是在采集侧记录HREF拉高的第一个PCLK对应的像素坐标在写入LCD显示缓存时按这个偏移量修正地址二是干脆在LCD驱动侧把有效窗口整体平移通过调整HBP和VBP来微调直到画面居中。第二种方法更快调几个参数就能看到效果。7. SignalTap调试与常见成像故障排查波形说明一切别靠猜7.1 SignalTap抓波形的正确姿势做这种项目Quartus自带的SignalTap II逻辑分析仪是调试神器。它可以在FPGA运行时实时抓取内部信号的波形而不影响逻辑运行实际会占一点资源。我调试这个工程时的标准抓数流程是对要观察的信号添加SignalTap节点至少包括PCLK、HREF、VSYNC、SCCB的SCL/SDA、FIFO写使能、FIFO读使能、LCD的HSYNC/VSYNC/DE、RGB输出数据。把采样时钟设为PCLK或逻辑主时钟。注意采样时钟的频率不能低于信号最高频率否则会出现混叠假象。设置触发条件。比如捕获VSYNC下降沿然后在触发前后各抓若干样本。观察波形时重点看VSYNC拉低后HREF是否正确拉高一定次数480次就结束每个HREF高电平期间PCLK上升沿个数是否为640个或800个含消隐FIFO的写使能是否和有效像素对齐。如果SignalTap里看到VSYNC和HREF的行为完全符合手册但LCD上就是不出图那问题基本就在LCD驱动侧回头查LCD时序参数的极性。7.2 常见故障现象与排查链路对照我整理一份这个工程最高频的故障排查表每一条都是我实际踩过的全黑屏屏幕不亮或纯黑先查LCD供电和背光。很多RGB屏的背光是独立LED供电不亮的话屏幕什么也看不见。再查LCD的DE信号如果DE恒为低屏幕就不会显示任何像素。最后查PCLK是否产生SignalTap或者示波器看一下LCD的PCLK引脚有没有25MHz左右的方波。硬件上有信号软件上才能谈逻辑。白屏或雪花噪点大概率是LCD的PCLK时钟极性反了。RGB屏的PCLK有上升沿采样和下降沿采样之分数据手册里通常写明诸如“Data is latched at rising edge of DOTCLK”或“falling edge”。把PLL输出的PCLK取反就能解决。画面上下跳动或滚动最常见原因是场同步不匹配。检查垂直总周期是不是525行以及VSYNC极性是否正确。如果VSYNC极性反了屏会检测不到场同步画面持续滚屏。画面有随机彩色噪点/雪花纹优先怀疑PCLK与D[7:0]之间的建立保持时间不足。把摄像头的PCLK延迟一下再采样用IO延时或增加寄存器打拍或者降低PCLK频率改CLKRC都能改善。图像偏色很严重比如红绿蓝分量错乱先检查OV7725是否配置为RGB565输出COM15寄存器再检查你的Verilog拼接顺序。RGB565的标准拼法是{R[4:0], G[5:0], B[4:0]}但有的屏内部是BGR顺序这时你把R和B交换即可。图像有横向条纹滚动优先查摄像头供电纹波。用示波器看摄像头电源引脚如果有几十mV以上的纹波外接一个100uF钽电容再试一试。也可以降低帧率把寄存器里自动曝光的速度调慢有时候能掩盖供电问题但治标不治本。7.3 我的排查顺序建议踩过这么多坑之后我形成了自己的固定排查顺序分享给你先确认摄像头出图用OV7725内置测试图案在LCD上直接显示彩条。如果彩条正常说明整条通路从摄像头输出到LCD显示是通的问题出在真实场景的配置上。如果彩条都不正常按“SCCB配置 - 采集时序 - 缓存读写 - LCD时序”逐段检查。再看帧率SignalTap计数器统计1秒内VSYNC出现的次数应该在60左右。如果远低于60检查CLKRC和COM4配置。最后看像素质量图像能出之后再慢慢调颜色矩阵、曝光、白平衡。新手最容易在这里浪费时间因为一开始图像就是偏色的但那是正常现象先把结构调对色彩是最后锦上添花的事。这个顺序让我在后面的多个摄像头项目里都少走了很多弯路。你先别急着把画面调到完美先把“能看到轮廓”这个目标达成再逐步精细化。我在实际调试这个工程时还有一个体会不要一开始就把所有模块全部写好再上板调试。我建议先只写LCD驱动用FPGA内部生成一个彩条测试图案显示在LCD上确认LCD时序没问题接着再接摄像头先把OV7725初始化通了用SignalTap或逻辑分析仪确认VSYNC和HREF正常最后才把采集、缓存、显示串起来。分阶段调试每一步都有明确的验证点出问题范围就缩小很多。像这样一头扎进去写完整工程再整体调一旦花屏你根本不知道该查哪里。本文还有配套的精品资源点击获取
返回列表