您的位置:首页 > 其它

s3c2440 + OV9650 +wince 摄像头拍照,cmos

2009-12-30 11:11 267 查看
来自:http://www.cnblogs.com/wogoyixikexie/archive/2009/11/04/1595676.html





嘿嘿,最近很晕,实在是太忙了,一个月没有写一篇技术文章,破了我的记录,公司的事情,还有其他网友的事情,搞的我好累,以前我每个月至少十篇原创的,趁着现在不是很忙,写一下
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

OK

,完工,发布博客!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: