Chapter 04: OV7670 视频接收解析
0赞Chapter 04: OV7670 视频接收解析
1. 写在前面的话
时间是2012年7月13号,00:14,我好累,明天继续吧,我想休息了,明天再战吧……
……
……
……
哈哈,2012年7月13号,17:12,再战!脑子里都是电路,因为没写一句话,脑袋里就生成了一块电路,什么DFF,MUX,AND,OR,发现自己俨然已经成了一部机器,行云流水的遨游,飘荡在0和1的世界里。
接下来解析CMOS摄像头视频接收方面的各种知识,一点点记录自己的心情,把混沌的脑袋整理的干净一点儿……
2. 配置OV7670寄存器
如上图所示,设置CMOS摄像头的各种模式,主要模式如下所示:
① VGA分辨率, RGB565模式
② 水平镜像,因为摄像头倒置了
③ 关闭PLL,直接使用外部时钟,打开LDO,使用内部电源
④ PCLK正常模式,不分频,XCLK=PCLK
⑤ 不设置彩条(这个可以用来调试)
一般我们采用RGB565模式,YUV模式会在后面解说;使用内部LDO比外部更加稳定,FPGA速度够快,因此PCLK都不用经过任何分频,直接输出,挑战OV的极限。
3. 视频信号分析
计算PCLK的参数,如下所示:
VSYNC: 510* Line = 3*tLine + 15*tLine +480*tLine
HREF: 784*tP = 640*tP + 144*tP
HSYNC: 784*tP = 80*tP + 45*tP + 640*tP + 19*tP
VGA RGB565, YUV 30fps:
PCLK = 784 * 510 * 30 * 2(byte) = 23990400 = 24MHz
因此手册才推介24MHz的XCLK输入。
简单的说CMOS图像的时序跟VGA时序非常雷同,只不过VGA时序使我们主动产生的,而CMOS时序是我们被动接受的。这需要我们根据固定的协议,时序,来准确接受每一个像素的数据。
其实CMOS摄像头的时序都差不多,因此可以一劳永逸,话说某公司的代码真的不咋地,但是用来做参考真的很不错,至少他已经告诉了你一个思路,让你不会那么茫然。
一下是RGB565下的OV摄像头的图像时序图,PCLK是连续的(这根Micron的摄像头一样),每一行有行有效信号,每一场有场有效信号,在场有效信号开始,第一个行有效信号的第一个数据便是第一个像素的高八位数据。每一个像素要分两次送。
我在SignalTap中也调试过,可以清晰的看得到,数据流的规则,PCLK上升呀对准的是每个数据的稳定期(当然PCLK的边沿可以在寄存器中调节),因此可以将PCLK作为整个时序逻辑的驱动时钟,直接作为DFF的使能时钟。
如下是将OV7670输出设置为移位1模式,可从SignalTap中看出,这些时序对于前期的调试,认知有很大的帮助,至少心里有了底。
4. 视频解码的Verilog实现
如果你用STM32玩过不带FIFO的OV7670 ,你肯定知道STM32的能力,能在80接口的LCD显示,坦白说是作弊了。首先你们用MCU初始化OV7670,同时初始化LCD为8Bit模式,然后,直接将OV7670 RGB565的数据输出给LCD,LCD内部经过捕获,叠加,直接输出视频。整个数据流没有经过单片机,这不属于你,可望而不可及。
当然,就算你用了带FIFO 的摄像头,可以通过关断来读取整幅图像,但是效率和速度就大大打折扣了,而且你休想实现VGA。是否还记的彬哥说过:“FPGA是万能的,但让FPGA为所欲为,是万万不能的!”我想说,这里,就是FPGA适合的星空,以独到的并行高速处理能力,准确无误实现数据的接受,搬迁,处理,输出,显示!接下来,我们就通过下面这个时序图,来实现OV7670数据的接受。其实很简单的!
在场信号(默认低有效),和行信号有效的同时,开始捕获数据;寄存第一个数据,拼接到第二个数据,实现一个完整像素的输出。同时在第二个数据有效的同时,输出一个使能信号给FIFO,作为SDRAM的异步缓存。当然,场有效信号,作为SDRAM的地址清零信号。真的有那么简单吗?
答案是是的,因为FPGA太强大了。
当然这部分中的数据拼接,也可以通过FIFO实现,异步FIFO有字节拼接功能,刻意按照您的设置拼接数据,如下图所示(这部分的设计,您可以自行发挥,我累了)
5. 特需注意的关节
1) 丢弃前10帧
OV明确指出,在配置完寄存器之后,保守估计,前10帧图像将会不稳定,介意舍弃。为此必须舍弃这10帧的数据,以保证后续图像处理的可靠(直接视频显示当然没关系,假设你看不到,当然我为了严谨,还是设计上了),如下:
因此在CMOS_Cpture中,刻意设置了Frame的就算,以至丢弃前10帧的数据,如下:
2) PCLK信号的处理
请看下面一下图像,你会发现图像偏移了,尽管我已经做了时序约束。很诚实的告诉你,彬哥经过了无数次测试,这真的不是代码问题,真的不是。。。
当然也不是杜邦线的问题,因为我是直插的。这部分当时猜想是因为PCLK并不是全局时钟,由于电路,布局布线上的不严谨,导致了时序的便宜,尽管布线已经OK了。猜想如果PCLK设置成全局时钟输入,那将会解决问题。
最后,自行设计了电路,直接将PCLK输入到全局时钟,图像如此的稳定,不再出现任何偏移,抖动等bug,非常低perfpect。
当然,这也不是唯一的解决方案,你完全可以用一个较高的时钟,去采样PCLK的上升沿,用边沿检测技术,来捕获使能,有效读取数据,这个,有待升级吧,反正现在perfect了。。
3) 杜邦线的处理
如上图,有些人用杜邦线直接连接了板子,说图像不稳定,设置什么都没有的。。。因为杜邦线串扰等原因,这真的不好。前些日子写过一篇文字,有关于杜邦线害死人的文章,《片间传输→高速数据的串扰》,此处不再累赘,有兴趣的请看:
http://blog.chinaaet.com/detail/28631.html
4) 最后,亮相一下当年调试过的记录,呵呵,秀一下(这不是0V7670哦)