原创 中星微zc301b摄像头

2013-1-14 09:51 2856 12 12 分类: MCU/ 嵌入式

 

硬件环境:友善之臂mini2440开发板+中星微zc301b摄像头

软件环境:linux2.6.29内核+上位机Ubuntu8.04

日    期:2012-12-19 于广州日顺电子科技有限公司

作   者:行者无疆 or 蜗牛

 

提示:感谢网友的倾情付出,我也是在网友的基础上整理,归类,然后通过实验验证罢了。

 

关于如何移植驱动,可以在google上搜索,

移植完驱动后,启动开发板,挂载NFS进入系统后,插上USB摄像头,串口出现如下信息:

usb 1-1: new full speed USB device using s3c2410-ohci and address 4

usb 1-1: device descriptor read/64, error -62

usb 1-1: device descriptor read/64, error -62

usb 1-1: new full speed USB device using s3c2410-ohci and address 5

usb 1-1: New USB device found, idVendor=0ac8, idProduct=301b

usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0

usb 1-1: Product: PC Camera

usb 1-1: Manufacturer: Vimicro Corp.

usb 1-1: configuration #1 chosen from 1 choice

gspca: probing 0ac8:301b

zc3xx: probe 2wr ov vga 0x0000

zc3xx: probe 3wr vga 1 0xe400

zc3xx: probe 3wr vga 2 0x0000

zc3xx: Sensor UNKNOW_0 force Tas5130

gspca: probe ok

 

 

 

 

 

# ./server_arm fastspeed.txt 

start 2.0...

Device name:PC Camera

Width:640 ~ 48

Height:480 ~ 32

Frames:4

Buffer size:475136

Offset:0

encoded:38016, 4228 bytes.

encoded:38016, 152 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

gspca: ISOC data error: [10] len=38, status=-84

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

encoded:38016, 12 bytes.

 

 

//-------------------------------------------------------------------------------------------------------------------

仔细查看,我们不难发现有两个问题:

其一:zc3xx: Sensor UNKNOW_0 force Tas5130,提示没有找到摄像头感光芯片,强制为Tas5130,其实中星微zc3xx摄像头感光芯片Tas5130CK,ID号为14。有些网友用的不是linux2.6.29内核版本,ID号为16,其实我们可以从内核中找到答案:

摘自

////////////////////////////////////

从内核zc3xx..c中copy

5, /* SENSOR_CS2102 0 */

5, /* SENSOR_CS2102K 1 */

4, /* SENSOR_GC0305 2 */

4, /* SENSOR_HDCS2020b 3 */

4, /* SENSOR_HV7131B 4 */

4, /* SENSOR_HV7131C 5 */

4, /* SENSOR_ICM105A 6 */

4, /* SENSOR_MC501CB 7 */

3, /* SENSOR_OV7620 8 */

4, /* SENSOR_OV7630C 9 */

4, /* SENSOR_PAS106 10 */

4, /* SENSOR_PAS202B 11 */

4, /* SENSOR_PB0330 12 */

4, /* SENSOR_PO2030 13 */

4, /* SENSOR_TAS5130CK 14 */

4, /* SENSOR_TAS5130CXX 15 */

3, /* SENSOR_TAS5130C_VF0250 16 */

 

既然找到问题,那就好办了,使用root权限,输入下列命令

# echo 14 > /sys/module/gspca_zc3xx/parameters/force_sensor

或者直接修改/sys/module/gspca_zc3xx/parameters/force_sensor文件,将文件清空然后输入14保存

 

重新插上你的摄像头就可以用了

 

当然,如果想一劳永逸呢,就编辑/etc/modprobe.conf加入这行

options gspca_zc3xx force_sensor=16

保存就OK! 但是这个一劳永逸的解决方法在此版本上不能用,没有modprobe.conf这个配置文件。

 

其二:

gspca: ISOC data error: [10] len=38, status=-84

解决USB摄像头出现ISOC data error的问题gspcav1-20071224/gspca_core.c: [spca50x_move_data:1611] ISOC data e

rror: [XX] len=XX, status=-84                 XX代表一些不定的数字

 

这个问题在我用VIDCAT的时候遇到了,这个主要是USB-host的问题。

下面是解决的办法:

修改drivers/usb/host/ohci-s3c2410.c文件中的s3c2410_start_hc函数,开始部分添加以下内容:

 

 

unsigned long s3c2410_upllcon=(unsigned long)ioremap(0x4C000008, 4);

 

unsigned long upllvalue=(0x38<<12)|(0x02<<4)|(0x02);

while(upllvalue!=__raw_readl(s3c2410_upllcon)){

__raw_writel(upllvalue,s3c2410_upllcon);

mdelay(1);

}

然后重新编译内核,即可解决。

 

 

好了,我们可以开始走上正途了:

重新拔了usb摄像头,再插上,弹出如下信息:

# echo 14 > /sys/module/gspca_zc3xx/parameters/force_sensor

# usb 1-1: USB disconnect, address 3

gspca: disconnect complete

usb 1-1: new full speed USB device using s3c2410-ohci and address 4

usb 1-1: New USB device found, idVendor=0ac8, idProduct=301b

usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0

usb 1-1: Product: PC Camera

usb 1-1: Manufacturer: Vimicro Corp.

usb 1-1: configuration #1 chosen from 1 choice

gspca: probing 0ac8:301b

zc3xx: probe 2wr ov vga 0x0000

zc3xx: probe 3wr vga 1 0xe400

zc3xx: probe 3wr vga 2 0x0000

zc3xx: sensor forced to 14

gspca: probe ok

 

 

激动人心的时刻到了,摄像头终于找到自己的家了,zc3xx: sensor forced to 14

 

运行我们的单帧采集测试程序,马上在同一目录下抓拍到图片。

# ./v4l 

open success!

set_norm success

init success!

size=475136

memory map success!

get picture success!

img address 0x40001000

 

测试程序源代码如下:

 

/*********************************************************

中星微摄像头zc301b感光芯片是Tas5130CK,在linux2.6.29版本中,

ID号14

 

# echo 14 > /sys/module/gspca_zc3xx/parameters/force_sensor

**********************************************************/

 

 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

//#include "v4l.h"

 

#include 

#include 

 

 

 

 

#define DEFAULT_DEVICE "/dev/video0"

 

 

 

 

#include 

#define norm VIDEO_MODE_NTSC

#define DEFAULT_FILE_NAME "picture" 

 

 

//PAL CIF NTSC tuner mode       

#define PAL_WIDTH 768  

#define PAL_HEIGHT 576 

#define CIF_WIDTH 352 

#define CIF_HEIGHT 288 

#define NTSC_WIDTH 80   // 

#define NTSC_HEIGHT 60 

#define DEFAULT_PALETTE VIDEO_PALETTE_RGB32 

 

struct _v4l_device

{

    int fd;

    struct video_capability capability;

    struct video_picture picture;

    struct video_window window;

    struct video_channel channel[8];

    struct video_mbuf mbuf;

    struct video_capture capture;

    struct video_buffer vbuffer;

    struct video_mmap mmap;

    unsigned char *map;

    int frame;

    int framestat[2]; 

};

typedef struct _v4l_device v4ldevice;

 

 

int v4l_open(char *dev,v4ldevice *vd)

{

    if (!dev){dev = DEFAULT_DEVICE;} ;

 

    if((vd->fd=open(dev,O_RDWR,10705))<0)

    {

        return -1;

    };

    if(v4l_get_capability(vd)<0)

        return -1;

    if(v4l_get_picture(vd)<0)

        return -1;

    return 0;

}

 

int v4l_get_capability(v4ldevice *vd)

{

    if(ioctl(vd->fd,VIDIOCGCAP,&(vd->capability))<0)

    {    

        perror("v4l_get_capability:");

        return -1;

    };

 

   return 0;

 

}

 

int v4l_get_picture(v4ldevice *vd)

{

    if(ioctl(vd->fd,VIDIOCGPICT,&(vd->picture))<0)

    {

        perror("v4l_get_picture");

        return -1;        

    };

 

   return 0;

 

 

}

 

 

 

int v4l_set_norm(v4ldevice *vd, int nrm)

 

int i;

for(i=0;i< vd->capability.channels ; i++){

// vd->channel=nrm ;

};

 

return 0;

 

}

 

 

 

 

 

int v4l_grab_init(v4ldevice *vd,int width,int height)

{

    vd->mmap.width=width;

    vd->mmap.height=height;

    vd->mmap.format=vd->picture.palette;                

    vd->frame=0;

    vd->framestat[0]=0;

    vd->framestat[1]=0;    

    return 0;

}

 

int v4l_mmap_init(v4ldevice *vd)

{

    if(v4l_get_mbuf(vd)<0)

        return -1;

    if((vd->map=mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0) )<0)

    {

        return -1;

    }

    return 0;

}

 

int v4l_get_mbuf(v4ldevice *vd)

{

    if(ioctl(vd->fd,VIDIOCGMBUF,&(vd->mbuf))<0)

    {

        perror("v4l_get_mbuf:");    

        return -1;

    }

    printf("size=%d\n",vd->mbuf.size);

return 0;

 

int v4l_grab_start(v4ldevice *vd,int frame)

{

    vd->mmap.frame=frame;

    if(ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->mmap))<0)

    {

        exit(-1);

        return -1;

    }

    vd->framestat[frame]=1;

    return 0;

}

int v4l_grab_sync(v4ldevice *vd,int frame)

{

    if(ioctl(vd->fd,VIDIOCSYNC,&frame)<0)

    {

        return -1;    

    }

    vd->framestat[frame]=0;

    return 0;

}

 

unsigned char * v4l_get_address(v4ldevice *vd)

{

  return (vd->map+vd->mbuf.offsets[vd->frame]);

//   return (vd->map+vd->mbuf.offsets[0]);

}

 

int v4l_close(v4ldevice *vd)

{

    close(vd->fd);

    return 0;

}

 

/*************************************************************/

 

/******************main.c************************/

 

/*name :main.c

 

  date:2009-5-20

 

  author:kevin

 

  copyright:all is reserved

 

************************************/

 

char *buffer=NULL;

 

int main()

{

 

 

    v4ldevice VD;

    v4ldevice *vd=&VD;

 

    int frame=0;

    int f_d;  

    

    int NUM, write_number = 0;

 

    f_d=open(DEFAULT_FILE_NAME,O_RDWR|O_CREAT,0666);    

    printf("f_d = %d \n",f_d);

    

    

    if(0==v4l_open("/dev/video0",vd)) 

        printf("open success!\n");

    else 

        printf("open failure\n");

 

    if(0==v4l_set_norm(vd,norm))

        printf("set_norm success\n");

    else

        printf("set_norm failure\n");

    if(0==v4l_grab_init(vd,NTSC_WIDTH,NTSC_HEIGHT))

 

        printf("init success!\n");

    else

        printf("init failure\n");

    if(0==v4l_mmap_init(vd))

        printf("memory map success!\n");

    else

        printf("memory map failure\n");

    if(0==v4l_grab_start(vd,frame))

        printf("get picture success!\n");

    else

        printf("get picture failure\n");     

 

    v4l_grab_sync(vd,frame);  

        

    buffer=(char *)v4l_get_address(vd);

    printf("img address %p\n",buffer);

          

    write_number = write(f_d,buffer,NTSC_WIDTH*3*NTSC_HEIGHT); //每一帧的字节数 80*60*3=14400byte

    

    printf("write_number = %d bytes\n",write_number);     

 

    v4l_close(vd);

    return 0;

    

}

 

Copy这段代码,注意查看驱动文件,在mini2440运行即可。

 

文章评论0条评论)

登录后参与讨论
我要评论
0
12
关闭 站长推荐上一条 /2 下一条