热度 12
2013-1-14 09:51
2875 次阅读|
0 个评论
硬件环境:友善之臂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: 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: len=38, status=-84 解决USB摄像头出现ISOC data error的问题gspcav1-20071224/gspca_core.c: ISOC data e rror: 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=(0x3812)|(0x024)|(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 ; struct video_mbuf mbuf; struct video_capture capture; struct video_buffer vbuffer; struct video_mmap mmap; unsigned char *map; int frame; int framestat ; }; 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; vd-framestat =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 =1; return 0; } int v4l_grab_sync(v4ldevice *vd,int frame) { if(ioctl(vd-fd,VIDIOCSYNC,frame)0) { return -1; } vd-framestat =0; return 0; } unsigned char * v4l_get_address(v4ldevice *vd) { return (vd-map+vd-mbuf.offsets ); // return (vd-map+vd-mbuf.offsets ); } 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运行即可。