ov9650 的调试 来自网络


2011-04-25 09:34:33|  分类: 摄像头 |  标签:ov9650  |举报|字号 订阅

Ov9650    Cam 采集帧速太低。只有5帧左右。开始怀疑是mjpg-streamer的速度问题。但是在网上看到一个网友也是用这个系统做的一个直升机模型,说速率可以达到30帧。怀疑,和他交流下来,经他提醒,他是修改了ov9650的初始参数,默认的驱动参数com7寄存器设置的是0x00,这样默认是输出1280x1024,所以慢,只要改成小图片模式输出就可以明显提高速率,按照这个思路我该为0x40,也即是vga模式(640x480).测试下来果然帧速提供很明显,说明书上说可以达到30帧。

可是这样引来了另一个问题,就是图像的左边出现了蓝色的直条。查手册估计和图像输出的横向扫描输出有关,看到HSTART,HSTOP的对应寄存器,不管怎么样,试试看,将HSTART和HSTOP的值都减小,哈哈,测试下来发现图像左边的蓝色带更宽了,发现规律,HSTART和HSTOP值增大相同的数量,估摸一下刚才减小的数量都应绿色带增加的宽度,按比例增大,哈哈效果很好,绿带消失了。耶! 测试同时用到这个参数register(1E),调整图像的水平和垂直翻转。Bit4垂直翻转,bit5水平翻转。谢谢51iMX论坛的c_music,是他给我的提示。   同时我启用了cam 的夜间帧速自动调整模式。Com11=0xb9.设定夜间模式帧速降为设定帧速的1/2.在光线不足的地方,画面不至于太黑。牺牲一部分帧速换来画面亮度。

 

OV9650 的配置

经过4天的调试摄像头终于可以拍照片保存到电脑上来,ov9650的调试走了不少弯路,一些教训总结如下:
1:OV9650是OmniVision公司的COMS摄像头,号称有130万像素,但是实际效果感觉不如CCD的,特别是远处的背景更糟糕。
2:OV9650的datasheet上写的寄存器控制协议是Serial Camera Control Bus (SCCB),还给了个时序图,但是它用的是两线制  的SCCB协议;根据它的时序图是可以兼容I2C的,两者在细微之处有点差别,但不影响,但实际应用中,都是后端平台的  I2C接camera的SCCB。可惜我没有仔细分析,愣是用两个GPIO模拟SCCB通信协议。此乃一错
3:对于OV9650,OmniVision公司是提供了参考寄存器配置的!一定要找相关人员要!(可能是他们的datasheet写得太烂的原因吧),可以我过分相信自己,没有找技术支持沟通!此乃二错
4v9650复位后默认配置是不能收到图像的!(在我的这个模式下:YUV422,VGA),当我在用I2C配置时,有的像的轮廓但颜色偏绿,我以为是没有配置起寄存器,但是实际上是配置起寄存器了,是YUV的顺序有问题!此乃三错
5:我们用的是杰得提供的VIA模块控制API,杰得的API多、复杂、有错且没有系统的说明,又由于我没有调试摄像头的相关经验,也没有弄明白杰得的VIA模块API。所以调试的时候没有图像,到底是摄像头输出问题?还是Z228接收处理的问题?无法判断!调试完摄像头了才知道杰得的库是可以输入4:2:2,输出4:2:0的!
我觉得调试步骤应该如下:
一:先要保证硬件没有问题!
1:首先要看RESET脚和,PDN脚.的电平是否正确,RESET:高电平复位.PDN:低电平工作正常。
    2:第一次调试I2C总线的时候,把示波器放在数据线上,抓图分析看OV9650是否应答。地址应该是60H不要搞错了!
    3:测试关键信号(这一小步要寄存器配置正确芯片正常工作了才有的):
           时钟输入信号pin13: 24M正弦波(外部晶振的输入)。
           时钟输出信号(像素频率):24M,变形了的像正弦波的方波。
           场同步信号Vsync:形如:   ----_----------_-----  :两个低电平之间是20ms左右(我测试的是22ms)
           行同步信号Href: 形如:   ----_----------_-----   :两个低电平之间是64us左右(我测试的是15.9Khz)
           以上三个信号是电视信号标准,一定要对。但是,在测试的时候有时候信号不是这个值,比如Vsync=34ms,why?我还没有搞清楚,请高手指点.
二: OV寄存器配置:
1:如果没有测试硬件,千万不要妄想配置寄存器! 也是我的调试原则,可惜这次我又违背了!嘚反省!
2: 用I2C读取OV9650的ProducaitonID寄存器【0x0A】【0x0B】:读出来版本号应该是0x9652,这里也一定要对,特别是你手上有几个信号的OV芯片的时候,不同型号的oV芯片,RESET复位信号不同,(有高有低哦!有一个网友就犯了这个错误浪费了四天),datasheet上没有说的很明白Reset是高复位还是低复位,我的小窍门是reset引脚内部有上拉电阻的话应该是低电平复位,有内部下拉电阻的话应该是高电平复位。
3:证明能够通过I2C控制OV9650后,将厂家给的或者网上下的相应的配置写入到ov9650。
4:如果配置大体正确,现在摄像头的数据应该出来了。
以下是厂家给的配置:共有三个VGA,CIF,SXVGA,输出都是YUV模式,如是时钟是24M,帧率是15fps,我只验证了VGA模式的,效果还可以!

 

如何实现OV9650摄像头拍照

camera OV9650 2010-06-23 20:52:18 阅读136 评论0   字号: 订阅

引用 http://www.cnblogs.com/wogoyixikexie/archive/2009/11/04/1595676.html

// 平台:wince5.0 2440 5.0 BSP (飞凌FL2440开发板)

// 发布日期:20091020

// 最后修改:2009年11月4日 8:40:45

        嘿嘿,最近很晕,实在是太忙了,一个月没有写一篇技术文章,破了我的记录,公司的事情,还有其他网友的事情,搞的我好累,以前我每个月至少十篇原创的,趁着现在不是很忙,写一下 camera 拍照的文档吧。

       EVC camera拍照的程序里面有

       ret=DeviceIoControl(m_hled,CAM_IOCTL_SAMSUNG_CAM_PR,NULL,NULL,(PBYTE)&image,NULL,NULL,NULL);

CAM_IOCTL_SAMSUNG_CAM_PR是个命令,发送到camera 驱动中,在

CIS_IOControl函数中会接收这个命令。

case CAM_IOCTL_SAMSUNG_CAM_PR:  // ID=0x522

                     RETAILMSG(MSG_EN_1,(_T("CAM_IOCTL_SAMSUNG_CAM_PR\r\n")));

                     Samsung_camcoder_pr(pBufOut);// 和拍照相关

                     break;

       从代码看,完全是通过DeviceIoControl取得camera驱动中的数据,然后建立个BMP图像,把数据填写到BMP里面,这样保存就形成了图像。嘿嘿,现在来看看这个Samsung_camcoder_pr(pBufOut)到底干了什么。

void Samsung_camcoder_pr(U8 *pBufOut)

{

       U8 *pImage;

       PINGPONG_PR prinfo;

       pImage = pBufOut;

       if ( rgb_flag )

       {

              prinfo.flag = 1;

              prinfo.rgb_address = rgb_address;

              memcpy(pImage, &prinfo, sizeof(PINGPONG_PR));

              rgb_flag = 0;

       }    

}

       从上面的代码可以看出,其实只是获得rgb_address,即把rgb_address传递给EVC应用程序,现在再来看rgb_address是从哪里来的。

       嘿嘿,找到了,在下面的函数中用到了!

 

 

void Buffer_preview_info_update()

{

//     U32 Y_size;

       int temp;

       unsigned int buffer_rgb;

      

       temp = (s2440CAM->rCIPRSTATUS>>26)&3;

       temp = (temp + 2) % 4;

 

       RETAILMSG(MSG_EN_2,(_T("preview index = %d, size %d\r\n"), temp, image_size));

 

       switch (temp)

       {

       case 0:

              buffer_rgb = s2440CAM->rCIPRCLRSA1;

              break;

       case 1:

              buffer_rgb = s2440CAM->rCIPRCLRSA2;

              break;

       case 2:

              buffer_rgb = s2440CAM->rCIPRCLRSA3;

              break;

       case 3:

              buffer_rgb = s2440CAM->rCIPRCLRSA4;

              break;

       default :

              buffer_rgb = s2440CAM->rCIPRCLRSA1;

              break;

       }

 

       buffer_rgb += VIRTUAL_ADDR_OFFSET;

#if 0

       RETAILMSG(MSG_EN_1,(_T("buffer_rgb = 0x%x\r\n"), buffer_rgb));

#endif

       if( rgb_flag )   RETAILMSG(MSG_EN_1,(_T("Buffer is not read\r\n")));

       rgb_flag = 1;

       rgb_address = buffer_rgb;// RGB的地址,这个地址到底是多大?万一我要显示很大的图像怎么办?在哪里有设置的?

}

       暂时不理会上面的疑问,看看Buffer_preview_info_update在哪里被调用了先。嘿嘿,这个在中断的线程里面呢。

if (cam_intr == BIT_SUB_CAM_P)

{

       RETAILMSG(1, (TEXT(" Camera interrupt.....BIT_SUB_CAM_P@@@@")));

       Buffer_preview_info_update();

}

 

哦,这个Buffer_preview_info_update();还是和P通道中断相关的,C通道根本没有用。这也正常,因为我们的BMP图像时裸二进制的,未经压缩,所以用P通道合情合理。以后有空也可以玩玩C通道拍照。

       到目前为止,这个拍照过程就走完了。现在就来解决一个问题,如何拍照保存成一个较大的图片,这个我已经有了点思路,午休后再来尝试一下。

       刚才看到一个拍照关键的地方

switch (temp)

       {

       case 0:

              buffer_rgb = s2440CAM->rCIPRCLRSA1;

              break;

       case 1:

              buffer_rgb = s2440CAM->rCIPRCLRSA2;

              break;

       case 2:

              buffer_rgb = s2440CAM->rCIPRCLRSA3;

              break;

       case 3:

              buffer_rgb = s2440CAM->rCIPRCLRSA4;

              break;

       default :

              buffer_rgb = s2440CAM->rCIPRCLRSA1;

              break;

       }

buffer_rgb =?是关键,看了一下,是在

void CamInit(U32 CoDstWidth, U32 CoDstHeight, U32 PrDstWidth, U32 PrDstHeight,

                     U32 WinHorOffset, U32 WinVerOffset,  U32 CoFrameBuffer, U32 PrFrameBuffer)

里面有下面的代码

/ preview port setting

s2440CAM->rCIPRCLRSA1=PrFrameBuffer;     // RGB帧地址,直接和保留的DMA地址绑定

s2440CAM->rCIPRCLRSA2=s2440CAM->rCIPRCLRSA1+PrDstWidth*PrDstHeight*multiplier;

s2440CAM->rCIPRCLRSA3=s2440CAM->rCIPRCLRSA2+PrDstWidth*PrDstHeight*multiplier;

s2440CAM->rCIPRCLRSA4=s2440CAM->rCIPRCLRSA3+PrDstWidth*PrDstHeight*multiplier;

// RGB帧地址是连续的,并且每一帧都保留了一定的空间(通过multiplier),当EVC程序拍照的时候就取得一帧的地址,然后就读下来。哦,看来要想把照片拍的大一些除了要修改应用以外,还要修改驱动中的PrDstWidth以及PrDstHeigh大小即可。

       好了,看懂了,明天再试试吧。

刚才我把camera EVC程序修改了一下图像大小,就立即产生了异常——原因是驱动中并没有设置足够的帧空间。

//width = 320;

//height = 240;

//

// if don't match the parameter of CamInit funtion---- U32 PrDstWidth, U32 PrDstHeight,

// will exception.Because the memory is not enough

//

width = 640;  

height = 480;

 

我把帧空间扩大了,

//

// 320*240

//

//CamInit(320, 240, 320, 240, 0, 0, COPIFRAMEBUFFER_B, COPIFRAMEBUFFER_A);

      

//

// 640*480

//

CamInit(320, 240, 640, 480, 0, 0, COPIFRAMEBUFFER_B, COPIFRAMEBUFFER_A);

现在是不会产生异常了,但是摄像头显示却变乱了,看来的确是要修改一下摄像头显示部分的代码。晕,拍照照样存在上面的异常,咋回事,现在这个空间都已经够了啊,难道是C通道和P通道的大小必须一致的?!改成一样试试。

我觉得还是内存空间不足造成的,因为我发现:

//

// 640*480

//

CamInit(320, 240, 640, 480, 0, 0, COPIFRAMEBUFFER_B, COPIFRAMEBUFFER_A);

看看COPIFRAMEBUFFER_B, COPIFRAMEBUFFER_A到底分配有多大?

#define COPIFRAMEBUFFER_A        0x32000000  // config.bib 82000000

#define COPIFRAMEBUFFER_B        0x32110000  // config.bib 82110000 

config.bib里面有

;===================for camera DMA==================

CAMERA                            82000000  00110000    RESERVED

CAMERA_CODE                 82110000  00800000    RESERVED

 

如果要存储640*480的图片,那么从代码中可以看出

/ preview port setting

s2440CAM->rCIPRCLRSA1=PrFrameBuffer;

s2440CAM->rCIPRCLRSA2=s2440CAM->rCIPRCLRSA1+PrDstWidth*PrDstHeight*multiplier;

s2440CAM->rCIPRCLRSA3=s2440CAM->rCIPRCLRSA2+PrDstWidth*PrDstHeight*multiplier;

s2440CAM->rCIPRCLRSA4=s2440CAM->rCIPRCLRSA3+PrDstWidth*PrDstHeight*multiplier;

这样就至少要物理内存空间640*480*2*4=0x00258000>0x00110000

也许问题就在这里了,嘿嘿,有办法解决。把P通道的内存和C通道的互换,这样就有空间了(0x00800000>0x00258000,先试试看看。晕死了,还是会产生一样的异常,为什么?在DNW窗口输出:

SENDING command id 0x03E8 to CDialog target.

Data Abort: Thread=985a3000 Proc=82936bb0 'Cameratest.exe'

AKY=00000801 PC=0005190c(Cameratest.exe+0x0004190c) RA=00051b70(Cameratest.exe+0x00041b70) BVA=7c0165e8 FSR=0000000f

找到对应的map文件地址

0001:000318fc ?PreSubclassWindow@CWnd@@UAAXXZ 000428fc f   uafxwced:wincore.obj

 0001:00031910       ?AfxWndProc@@YAJPAUHWND__@@IIJ@Z 00042910 f  uafxwced:wincore.obj

 

觉得不对劲啊,看来不能用普通的方法去排除这个异常。

       哦,目前产生异常,是否是这样原因?就是图像太大了,没有读完,这个camera又产生下一帧的中断了?我试试关闭中断在读的过程中

s2440INT->rINTMSK |= BIT_CAM;// 关闭camera中断

读图片的过程

s2440INT->rINTMSK &= ~BIT_CAM;// 打开camera中断

晕,关闭也没有用。后来娜娜提示我犯了严重的错误。真的好低级啊,居然是内存分配不够大。

//

       //320*240

       //

       //WORD width=GetSystemMetrics(SM_CXSCREEN);

       //WORD height=GetSystemMetrics(SM_CYSCREEN);

       BYTE* DDBdata=new BYTE[width*height*2];

因为是3.5寸的LCD,导致了这个郁闷的事情。OK,后来拍照成功!不过显示倒是不行了!再次按照如下修改,再次显示成功。

memcpy((void *)(IMAGE_FRAMEBUFFER_UA_BASE+ (240*2*pos_y + pos_x*2) + y*240*2),(void *)buffer_rgb,(size_x*2));

              //RETAILMSG(1,(_T("IMAGE_FRAMEBUFFER_UA_BASE(2)\r\n")));

              //跳到图像的下一行开始指针

              //buffer_rgb += (QCIF_XSIZE*2);      //320*240

              buffer_rgb += (640*2);  // 640*480

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值