解决ov5640摄像头画面撕裂错位问题
解决ov5640摄像头画面撕裂错位问题问题背景之前移植过ov5640的驱动当时提及到了一个驱动能力的概念。这个驱动能力的高低就是用来控制引脚输出电流的大小驱动能力设置越高引脚输出的电流越大那么时序波形就越清晰前沿和后尾小。反之驱动能力低的话输出的时序波形可能前沿和后尾会拖的比较长波形不规范。当时我们设置驱动能力等级为2的时候会出现画面滚动撕裂。然后将驱动能力降为1的时候画面滚动停止。然后偶尔会出现滚动错位的情况。由于出现画面撕裂的情况是偶尔发生我当时以为是硬件的问题便没有深究最近在使用摄像头的时候频频出现画面错位撕裂的情况于是就去找原因最终找到了现在来分析一下。驱动能力较高的时候画面撕裂错位并且向左滚动降低驱动能力画面停止滚动但是有时会出现错位撕裂的情况分析原因1、自行分析出现画面错位的可能原因第一次碰见这种情况我以为是跟分辨率设置有关我第一反应是应用程序里面在实现零拷贝的时候使用mmap进行内存映射时没用映射好导致了画面错位了原本应该在左边的画面跑到右边来显示了但是经过一系列排查并没用发现应用程序有明显的错误。而且如果是应用程序映射出错那么应该从一开始就出现错误而且不会出现这种时好时坏的场景。2、上网寻找他人经验于是我就去看博客然后就看到一篇关于摄像头画面撕裂错位可能原因这里提及到dvp接口数据采集时序的问题我去看了一下原理图发现正点原子的imx6ull开发板csi接口使用的是8位并行的DVP接口。所以接下来我们来分析一下DVP接口工作时序来找一下原因。3、DVP时序1、DVP的信号以及组成信号方向作用PCLK输出像素时钟一个周期对应一个像素数据如48MHz可以自己指定采用边沿MCLK/XCLK输入传感器外部时钟输入如24MHz由主控或晶振提供为 Sensor 提供基准时钟用于内部 PLL 分频生成 PCLK、HSYNC、VSYNC 等信号。VSYNC输出帧同步信号每帧触发一次有效电平期间采集一帧数据可自己设置有效电平HREF/HSYNC输出行同步信号每帧触发一次有效电平期间采集一行数据可以自己指定有效电平D[0:11]输出并行数据线8/10/12bit每个PCLK周期传输一个像素数据。注意这里我们要保证一个信号在主机接口和传感器里面的有效电平必须被设置成一样的。2、时序分析我们先来分析行输出时序①、可以看到主机csi接口在PCLK时钟信号上升沿的时候采集数据所以应该是上升沿有效。①、可以看到在HREF行同步信号为高电平期间data传输一行的数据说明HREF是高电平有效的在其低电平期间PCLK采集到的数据被当成无效数据。并且HREF信号的占空比取决于我们设置的分辨率分辨率越高那么这个信号的高电平持续时间越长。帧时序分析可以看到这里一帧起始的时候会出现一个脉冲信号表示一帧开始传输了。在VSYNC为低电平期间传输一帧的数据所以它应该是低有效的。4、总结图片撕裂可能原因①、第一个原因就是我们在主机csi驱动里设置的PCLK采样边沿和摄像头里配置的数据输出边沿不一致导致的。传感器可能在PCLK上升沿输出数据而SoC却配置成在下降沿采样结果每两个像素就会错一位造成整体图像左右偏移半个字节表现为严重的色块和错位。②、HREF极性配置不一致比如我们摄像头里指定HREF在高电平有效但是在主机csi驱动里面却指定了HREF在低电平有效。此时HREF高电平周期一定是大于低电平的高电平期间要准备一行像素数据所以会出现这种情况摄像头在HREF高电平期间根据分辨率准备了一行的数据虽然它在低电平期间也在采集数据但是数据的大小没有一行那么多。而我们主机驱动认为低电平有效所以我们主机驱动拿到的是低电平期间那些大小不足一行的数据将其显示最终会出现的情况就是画面上下翻滚。③、VSYNC极性配置不一致同理就是我们给摄象头指定了是低电平有效然后又给主机csi指定了高电平有效。那么摄像头在低电平期间准备了一帧的数据我们主机读取高电平期间的数据。由于低电平的周期长所以高电平期间读取到的数据不足一帧那么主机将其显示就会出现画面撕裂滚动的问题。所以初步应该得出结论是VSYNC/HSYNC这两个极性引脚的极性在主机和摄像头寄存器里配置不一样解释一下为什么我们调高驱动能力时画面错位撕裂现象明显降低驱动能力时现象就是偶然出现。这里我没有示波器无法抓取波形我的猜测是在驱动能力较高的情况下引脚输出的电流越大那么时序波形就会比较规范完整波形的前沿和后尾短爬升块。这个时候VSYNC高低电平持续时间差距明显。所以一旦极性配置错误就会马上将问题反应出来。降低驱动能力导致引脚输出电流降低波形模糊前沿和后尾拉长容易导致误判从而导致VSYNC信号的高低电平持续时间看起来差不多大小。那么就类似于波形占空比是50%的情况高低电平采样的数据量都是一帧的大小所以极性反转了也没关系。解决1、我们查看一下ov5640的手册可以看到这里配置引脚极性的寄存器是0x47403、我们验证一下这些引脚配置不同会出现什么情况1、我们先验证一下寄存器正常配置的情况也就是将寄存器配置为0x21这里我们只需要在初始化的时候将这组寄存器配置添加到初始化数组就行;staticstructreg_valueov5640_global_init_setting[]{{0x3008,0x42,0,0},{0x3103,0x03,0,0},{0x3017,0xff,0,0},{0x3018,0xff,0,0},{0x3034,0x1a,0,0},{0x3037,0x13,0,0},{0x3108,0x01,0,0},{0x3630,0x36,0,0},{0x3631,0x0e,0,0},{0x3632,0xe2,0,0},{0x3633,0x12,0,0},{0x3621,0xe0,0,0},{0x3704,0xa0,0,0},{0x3703,0x5a,0,0},{0x3715,0x78,0,0},{0x3717,0x01,0,0},{0x370b,0x60,0,0},{0x3705,0x1a,0,0},{0x3905,0x02,0,0},{0x3906,0x10,0,0},{0x3901,0x0a,0,0},{0x3731,0x12,0,0},{0x3600,0x08,0,0},{0x3601,0x33,0,0},{0x302d,0x60,0,0},{0x3620,0x52,0,0},{0x371b,0x20,0,0},{0x471c,0x50,0,0},{0x3a13,0x43,0,0},{0x3a18,0x00,0,0},{0x3a19,0x7c,0,0},{0x3635,0x13,0,0},{0x3636,0x03,0,0},{0x3634,0x40,0,0},{0x3622,0x01,0,0},{0x3c01,0x34,0,0},{0x3c04,0x28,0,0},{0x3c05,0x98,0,0},{0x3c06,0x00,0,0},{0x3c07,0x07,0,0},{0x3c08,0x00,0,0},{0x3c09,0x1c,0,0},{0x3c0a,0x9c,0,0},{0x3c0b,0x40,0,0},{0x3810,0x00,0,0},{0x3811,0x10,0,0},{0x3812,0x00,0,0},{0x3708,0x64,0,0},{0x4001,0x02,0,0},{0x4005,0x1a,0,0},{0x3000,0x00,0,0},{0x3004,0xff,0,0},{0x300e,0x58,0,0},{0x302e,0x00,0,0},{0x4300,0x30,0,0},{0x501f,0x00,0,0},{0x440e,0x00,0,0},{0x5000,0xa7,0,0},{0x3008,0x02,0,0},{0x4740,0x21,0,0},};//修复画面撕裂{0x4740, 0x21, 0, 0},2、只有PCLK引脚极性配置不同的情况将寄存器配置为0x01造成整体图像左右偏移半个字节表现为严重的色块和错位。3、只有HREF极性不同的情况将寄存器配置为0x23配置错误导致每一行都偏移最终图像上下翻滚4、VSYNC极性配置出错0x20这里出现的情况就是刚开始提到的图片撕裂然后滚动。

相关新闻