OV9712 CMOS基于JZ4775调试(三)

    新拿到的硬件,是好是坏,或者有没有一些大意或细节的错误,当然需要驱动程序并结合一些电气工具如(示波器)去检测.

1.SCCB:

 当然这是最首检测也是必须检测的.这里我是用iic-tools工具(LINUX平台支持用户空间驱动的项目,需要内核编译相关的支持).源码可以网上搜索移植.后续会提供我这边提供整理简化的IIC-TOOLS源码.iic-tools是LINUX平台调试IIC设备的利器.一共有i2cdetect,i2cset,i2cget,i2cdump四个工具,可以遍历iic总线上的设备.其具体用法可网上搜索.OV9712标识了其SCCB设备地址为0x60,如果i2cdetect出来的结果和其设备地址有出入,就需要检查一下硬件了.

    当然,前期是可以用iic-tools工具大体检测,如果是有特殊接口API要求,则就需要具体的API编程.例如下面是我获取OV9712的PID的函数:

unsigned short ov9712GetId(int iic_fd)
{
        unsigned short pid = 0;
        unsigned char tmp = 0;

        iic_set_addr(iic_fd,OV9712ADDR);

        tmp = iic_read(iic_fd,PIDHADDR);
        pid = tmp;
        pid = pid << 8;

        tmp = iic_read(iic_fd,PIDLADDR);
        pid = pid | tmp;

        if(0x9711 == pid)
                printf("Found Sensor OV9712.So Lucky!\n");
        else
                printf("Oops:Miss OV9712.\n");

        return pid;
}
    0x9711是OV9712的产品ID,可以查看其数据手册.

    这里曾遇到个问题,就是SCCB通讯失败,原因是OV9712必须有MCLK才可以SCCB通讯的.


2.初始化OV9712:

  确认SCCB通讯是没问题的,就直接往OV9712堆sample code吧.把原厂提供的初始化代码通过SCCB协议,往里面塞.塞完寄存器后大体量一下MCLK、VSYNC、HSYNC、PCLK及DATA引脚,都有信号输出并且是正常的.截取了一部分原始数据铺在320x240的屏上显示只有一些彩条乱七八糟的.出现这种情况当时就往两个方向想了:

一个是极性问题;第二个对出来的图像数据直接铺屏(RGB565)的问题.

    2-1.极性匹配:

  厂家提供的代码里面间没有对VSYNC、HSYNC和PCLK的极性进行重新配置,就是采用默认的.于是查找OV9712数据手册找到VSYNC、HSYNC、PCLK的极性控制寄存器.如下:

OV9712 CMOS基于JZ4775调试(三)_第1张图片

  可见,OV9712的VSYNC、HSYNC默认的极性是Positive,即上升沿有效.

  注意,这里不要这里的寄存器坑了,HSYNC默认确实是positive,但是前提是你选定的是HSYNC模式.OV9712支持三种模式:HREF、HSYNC、CCIR565.默认的就是HERF模式而不是HSYNC模式.HERF和HSYNC是同一个pin脚,不同的是,HERF模式下,HERF引脚为低的时候VSYNC引脚输出才有效.见OV9712的数据手册的时序图,如下:

  OV9712 CMOS基于JZ4775调试(三)_第2张图片

  因此,在HREF模式下,是下降沿有效的.在这种模式下主控端需要配置HSYNC引脚为下降沿有效.我把JZ4776主控端配置成上升沿有效的时候,是获取不了图片的.既然废弃了HSYNC行同步,那么会不会出现行同步不一致而导致主控拒绝接收数据呢?个人认为,有VSYNC足够了,它引发了中断,就意味着一帧图像传输完毕,主控端就可以去处理数据了,HSYNC是可以被忽略的.如果遇到一些平台比较严格的话,还需要处理HSYNC同步的话,就具体处理了.

        PCLK的极性如下:

OV9712 CMOS基于JZ4775调试(三)_第3张图片

  因此,我们可以确定HREF模式下PIN脚VSYNC、HREF(HSYNC)、PCLK的极性分别为:

VSYNC:上升沿;
HERF(HSYNC):下降沿;
PCLK:上升沿.
  因此,再根据设备去配置主控端的相应极性:

  默认的VSYN和PCLK极性是一致的,主要是把HSP配置为1(即下降沿有效).


 2-2.接收图像的顺序:

 一般CPU的CIM控制器都有从SENSOR端过来的接收到的数据进行重组排序处理的.一般而言,SENSOR端输出的是YUV或RAW RGB,一般而言,数据手册都可以找到明确其明确格式,比如OV9712的图像输出格式就是BAYER(RAW DATA)中的一种.从其数据手册可以看到如下字样:

The color filters are arranged in a Bayer pattern. The primary color BG/GR array is arranged in line-alternating fashion.
 「小技巧:」无论是YUV还是RAW DATA,如果是接收顺序反了的话,一般都有轮廓.可以适当尝试一下别的字节重组顺序.

 JZ4775对从SENSOR接收过来的4个字节拼成32位的字,有下面8种方式:

OV9712 CMOS基于JZ4775调试(三)_第4张图片   

 这里选择第五种方式,即3'b100.高低位调转的方式.

    核对了上述两点之外,出来的图像依然看不出图像的完整性.配置依然可能存在问题,镜头也没调焦距,上层转换函数也有可能存在问题.这三个方面的因素都有可能导致同样的现象.于是想了下有没有更好更直接的快捷方式.通过查阅OV9712的数据手册,发现其提供了个test pattern模式.进入这种模式下,显示8段彩条.如下:


    在OV9712提供的另一款"应用程序编程手册"可以知道进入test pattern模式通过下面寄存器设置:

  当然,还要设置寄存器0xca进入TestPattern模式.代码如下:

void ov9712TestPattern(int iic_fd)
{
        iic_write(iic_fd,0xca,0x24);
        iic_write(iic_fd,0x12,0x02);
        iic_write(iic_fd,0x97,0x88);
}
  然后把SENSOR端过来的数据转RGB565保存起来,发现图片有断层情况.后来检查发现是转换函数的bmp头构造得有问题.修复后效果和test pattern一致.为了调试方便,决定把转换出来的RGB565(1280 X 800)显示在2.8寸屏(320 x 240)上.通过跳行跳列实现.代码如下:

/*
Function:
        Skip One Row And One Column.    
Date:
        2014-3-29
Author:
        SE7EN
*/
void skipPiexl1(const u16 *inBuf,u16 *outBuf,const u32 width,const u32 height,u32 div)
{
        assert((inBuf && outBuf && (0 == (width % 4) && (0 == (height % 4)) && (0 == (div % 4)))));

        const u16 *pInW = inBuf;
        u16 *pOut = outBuf;
        u32 i = 0,j = 0,k = 0,sum = 0,aver = 0;

        for(i = 0; i < height; i+=2)
        {
                for(j = 0; j < width; j+=2)
                {
                        *pOut = *pInW;
                        pOut++;
                        pInW +=2;
                }

                pInW = pInW + width;
        }
}
    因为我的是竖屏,因此还需要把两次缩放的像素buf旋转90度,代码如下:

/*
Function:
        Operation For RGB.
Date:
        2014-3-29
Author:
        SE7EN
*/

#include "skippiexl.h"
void rgb565_rotate90(const u16 *input, u16 *output,u32 width_in,u32 height_in)
{        
        const u16 *pIn=input;
        u16 *pOut=output;

        int i,j;

        for(i=0; i<height_in; i++)
        {
                for(j=0; j<width_in; j++)
                {
                        *pOut = *pIn++;
                        pOut = output+height_in*j + i;
                }
        }
}


3.小结:

 SENSOR其实是挺复杂的一个东西,很多过中涉及的概念都只是有个笼统的概念.在此作录备忘,后续还需要调试图像质量,这个只能靠技术支持了.

 


你可能感兴趣的:(OV9712 CMOS基于JZ4775调试(三))