linux摄像头驱动.doc_第1页
linux摄像头驱动.doc_第2页
linux摄像头驱动.doc_第3页
linux摄像头驱动.doc_第4页
linux摄像头驱动.doc_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

46基于V4L2的视频驱动开发基于V4L2的视频驱动开发编写基于V4L2视频驱动主要涉及到以下几个知识点: 摄像头方面的知识 要了解选用的摄像头的特性,包括访问控制方法、各种参数的配置方法、信号输出类型等。 Camera解码器、控制器 如果摄像头是模拟量输出的,要熟悉解码器的配置。最后数字视频信号进入camera控制器后,还要熟悉camera控制器的操作。 V4L2的API和数据结构 编写驱动前要熟悉应用程序访问V4L2的方法及设计到的数据结构。 V4L2的驱动架构 最后编写出符合V4L2规范的视频驱动。本文介绍基于S3C2440硬件平台的V4L2视频驱动开发。摄像头采用OmniVision公司的OV9650和OV9655。主要包含以下几个方面的内容:视频驱动的整体驱动框架3C2440 camera控制器+ov9650(ov9655)V4L2 API及数据结构V4L2驱动框架ov9650(ov9655)+s3c2440+V4L2实例一、 视频驱动的整体框架视频驱动的整体框架见下图:二、S3C2440 camera控制器+ov9650(ov9655)(1)S3C2440 camera控制器介绍S3C2440支持ITU-R BT601/656格式的数字图像输入,支持的2个通道的DMA,Preview通道和Codec通道,参见下图。Preview通道可以将YCbCr4:2:2格式的图像转换为RGB(16bit或24bit)格式的数据,并存放于 为Preview DMA分配的内存中,最大分辨率为640*480。主要用于本地液晶屏显示。如果将Preview DMA的内存和Framebuffer内存重叠的话,就可以实现采集直接输出到液晶屏上了。Codec通道可以输出YCbCr4:2:0或YCbCr4:2:2格式到为Codec DMA分配的内存中。最大分辨率为4096*4096。主要用于图像的编解码处理。上图中的window cut功能是指在图像可以先做一个裁剪。通过设置CIWDOFST完成此功能,见下图。图像进入P、C通道后,各自的scaler单元还可以对其进行缩放、旋转等处理。S3C2440 camera控制器支持乒乓存储。为了防止采集和输出之间的冲突,采用了乒乓存储方式。每次采集一帧后,自动转到下一个存储区。如果你因为内存空间不足,不想使用此功能的话,可以将四个区域设置到同一块空间。在做图像处理时,需要关注到最后存储区中的图像格式,如codec通道硬件自动把Y、Cb、Cr分离存储。S3C2440 camera 控制器Last IRQ功能的使用,也是需要掌握的。如果处理不好,输出的图像效果会受影响。控制器会在每个VSYNC下降沿判断ImgCptEn信号等命令。如果在下降沿发现ImgCptEn信号有效,则产生 IRQ中断。然后才开始一帧图像的真正采集。而如果在VSYNC下降沿判断到ImgCptEn为低电平且之前LastIRQEn没有使能,则不会产生任何中断,且不会再进行下一帧的采集。如果你想在ImgCptEn关闭后,一帧采集完后产生一个中断通知你,那么就需要在最后一次中断产生前(stop capturing后的vysnc下将沿)使能lastirq就可以了。我在移植linux驱动时就遇到了一个Last IRQ的问题。现象是输出图像上面总是有一条比其它部分反应慢。采集运动图像,就能看出现象。查看代码是因为没有设立lastirq,因为每次如果不在 lastirq产生的情况下读取,图像缓冲中的数据是不稳定的,可能照成图像不完整。修改代码支持lastirq后,问题解决。Camera控制器时钟设置也是需要注意的,ov9650需要Camera控制器为其提供时钟。提供给外部摄像头的时钟是由UPLL输出时钟分频得到的。而CAMIF的时钟是由HCLK提供的。本例中,提供给ov9650的时钟为24M。(2)ov9650(ov9655)设置方法OV9650是OmniVision公司的COMS摄像头,130万像素,支持SXVGA、VGA、QVGA、CIF等图像输出格式。最大速率在SXVGA时为15fps,在VGA时为30fps。OV9650摄像头时序如下图:上图中D9:2用于8-bitYUV或者RGB565/RGB555(D9MSB、D2LSB)。D9:0用于10-bit RGB。本例中使用8-bit YUV模式。我手边开发板的Camera和S3C2440的接线原理图如下(对应camera中具体的信号名称参见前文的驱动整体架构图)。注:GPG12用于PWEN信号OV9650摄像头设置方法是通过SCCB总线设置SCCB可以看作是一种简化的I2C总线,可以使用IO模拟SCCB时序。(3)编写ARM测试代码测试camera功能在Keil环境下编写一个测试代码完成从摄像头采集图像输出到液晶屏。下面列出程序的流程。(4)编写测试代码过程中常见的问题摄像头寄存器的配置因为摄像头有很多寄存器,可能一下无法理解里面所有的配置含义,所以开始时希望得到一份可用的配置。但往往从别人的测试代码中拿到配置后,仍然无法使用。我这里列出几个可能的原因:(1)摄像头中的图像输出格式和你在camera控制器中设置的不一致,同一个摄像头可以设置多种输入格式,如:YCbYCr或CbYCrY。(2)图像输出的一些时序和你的camera控制器设置不一致,摄像头可以设置一些时序,如:图像数据在CAMPCLK的上升沿有效还是下降沿有效。(3)注意输出图像的格式和Framebuffer控制器的匹配,如字节顺序等问题。Ov9650和ov9655的使用区别这里主要列出两者之间在复位信号上有差别,ov9650是高电平复位,而ov9655是低电平复位。三、V4L2 API 及数据结构 V4L2 是 V4L 的升级版本,为 linux 下视频设备程序提供了一套接口规范。包括一套数据结构和底层 V4L2 驱动接口。 1 、常用的结构体在内核目录 include/linux/videodev2.h 中定义 struct v4l2_requestbuffers / 申请帧缓冲,对应命令 VIDIOC_REQBUFS struct v4l2_capability / 视频设备的功能,对应命令 VIDIOC_QUERYCAP struct v4l2_input / 视频输入信息,对应命令 VIDIOC_ENUMINPUT struct v4l2_standard / 视频的制式,比如PAL ,NTSC ,对应命令 VIDIOC_ENUMSTD struct v4l2_format / 帧的格式,对应命令VIDIOC_G_FMT 、VIDIOC_S_FMT 等 struct v4l2_buffer / 驱动 中的一帧图像缓存,对应命令VIDIOC_QUERYBUF struct v4l2_crop / 视频信号矩形边框 v4l2_std_id / 视频制式 2 、常用的 IOCTL 接口命令也在 include/linux/videodev2.h 中定义 VIDIOC_REQBUFS / 分配内存 VIDIOC_QUERYBUF / 把 VIDIOC_REQBUFS 中分配的数据缓存转换成物理地址 VIDIOC_QUERYCAP / 查询驱动功能 VIDIOC_ENUM_FMT / 获取当前驱动支持的视频格式 VIDIOC_S_FMT / 设置当前驱动的频捕获格式 VIDIOC_G_FMT / 读取当前驱动的频捕获格式 VIDIOC_TRY_FMT / 验证当前驱动的显示格式 VIDIOC_CROPCAP / 查询驱动的修剪能力 VIDIOC_S_CROP / 设置视频信号的矩形边框 VIDIOC_G_CROP / 读取视频信号的矩形边框 VIDIOC_QBUF / 把数据从缓存中读取出来 VIDIOC_DQBUF / 把数据放回缓存队列 VIDIOC_STREAMON / 开始视频显示函数 VIDIOC_STREAMOFF / 结束视频显示函数 VIDIOC_QUERYSTD / 检查当前视频设备支持的标准,例如 PAL 或 NTSC 。 3 、操作流程 V4L2 提供了很多访问接口,你可以根据具体需要选择操作方法。需要注意的是,很少有驱动完全实现了所有的接口功能。所以在使用时需要参考驱动源码,或仔细阅读驱动提供者的使用说明。 下面列举出一种操作的流程,供参考。 ( 1 )打开设备文件 int fd = open(Devicename,mode); Devicename : /dev/video0 、 /dev/video1 Mode : O_RDWR | O_NONBLOCK 如果使用非阻塞模式调用视频设备,则当没有可用的视频数据时,不会阻塞,而立刻返回。 ( 2 )取得设备的 capability struct v4l2_capability capability ; int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability); 看看设备具有什么功能,比如是否具有视频输入特性。 ( 3 )选择视频输入 struct v4l2_input input ; 初始化 input int ret = ioctl(fd, VIDIOC_QUERYCAP, &input); 一个视频设备可以有多个视频输入。如果只有一路输入,这个功能可以没有。 ( 4 )检测视频支持的制式 v4l2_std_id std; do ret = ioctl(fd, VIDIOC_QUERYSTD, &std); while (ret = -1 & errno = EAGAIN); switch (std) case V4L2_STD_NTSC: / case V4L2_STD_PAL: / ( 5 )设置视频捕获格式struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; fmt.fmt.pix.height = height; fmt.fmt.pix.width = width; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; ret = ioctl(fd, VIDIOC_S_FMT, &fmt); if(ret) perror(VIDIOC_S_FMTn); close(fd); return -1; ( 6 )向驱动申请帧缓存 struct v4l2_requestbuffers req; if (ioctl(fd, VIDIOC_REQBUFS, &req) = -1) return -1; v4l2_requestbuffers 结构中定义了缓存的数量,驱动会据此申请对应数量的视频缓存。多个缓存可以用于建立 FIFO ,来提高视频采集的效率。 ( 7 )获取每个缓存的信息,并 mmap 到用户空间 typedef struct VideoBuffer void *start; size_t length; VideoBuffer; VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) ); struct v4l2_buffer buf; for (numBufs = 0; numBufs nr0 :次设备号 =base (基准值,受 type 影响) +nr ; 否则:系统自动分配合适的次设备号 具体驱动只需要构建 video_device 结构,然后调用注册函数既可。 如: zc301_core.c 中的 err = video_register_device(cam-v4ldev, VFL_TYPE_GRABBER, video_nrdev_nr); Video 核心层( drivers/media/video/videodev.c )提供了注销函数 void video_unregister_device(struct video_device *vfd) 2 、 struct video_device 的构建 video_device 结构包含了视频设备的属性和操作方法。参见 zc301_core.c strcpy(cam-v4ldev-name, ZC0301P PC Camera); cam-v4ldev-owner = THIS_MODULE; cam-v4ldev-type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; cam-v4ldev-fops = &zc0301_fops; cam-v4ldev-minor = video_nrdev_nr; cam-v4ldev-release = video_device_release; video_set_drvdata(cam-v4ldev, cam); 大家发现在这个 zc301 的驱动中并没有实现 struct video_device 中的很多操作函数 , 如 : vidioc_querycap 、 vidioc_g_fmt_cap 等。主要原因是 struct file_operations zc0301_fops 中的 zc0301_ioctl 实现了前面的所有 ioctl 操作。所以就不需要在 struct video_device 再实现 struct video_device 中的那些操作了。 另一种实现方法如下: static struct video_device camif_dev = .name = s3c2440 camif, .type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_SUBCAPTURE, .fops = &camif_fops, .minor = -1, .release = camif_dev_release, .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, .vidioc_g_fmt_cap = vidioc_g_fmt_cap, .vidioc_s_fmt_cap = vidioc_s_fmt_cap, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, ; static struct file_operations camif_fops = .owner = THIS_MODULE, .open = camif_open, .release = camif_release, .read = camif_read, .poll = camif_poll, .ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = camif_mmap, .llseek = no_llseek, ; 注意 : video_ioctl2 是 videodev.c 中是实现的。 video_ioctl2 中会根据 ioctl 不同的 cmd 来 调用 video_device 中的操作方法。 3 、 Video 核心层的实现 参见内核 /drivers/media/videodev.c ( 1 )注册 256 个视频设备 static int _init videodev_init(void) int ret; if (register_chrdev (VIDEO_MAJOR, VIDEO_NAME, &video_fops) return -EIO; ret = class_register(&video_class); 上面的代码注册了 256 个视频设备,并注册了 video_class 类。 video_fops 为这 256 个设备共同的操作方法。 ( 2 ) V4L2 驱动注册函数的实现 int video_register_device(struct video_device *vfd, int type, int nr) int i=0; int base; int end; int ret; char *name_base; switch(type) / 根据不同的 type 确定设备名称、次设备号 case VFL_TYPE_GRABBER: base=MINOR_VFL_TYPE_GRABBER_MIN; end=MINOR_VFL_TYPE_GRABBER_MAX+1; name_base = video; break; case VFL_TYPE_VTX: base=MINOR_VFL_TYPE_VTX_MIN; end=MINOR_VFL_TYPE_VTX_MAX+1; name_base = vtx; break; case VFL_TYPE_VBI: base=MINOR_VFL_TYPE_VBI_MIN; end=MINOR_VFL_TYPE_VBI_MAX+1; name_base = vbi; break; case VFL_TYPE_RADIO: base=MINOR_VFL_TYPE_RADIO_MIN; end=MINOR_VFL_TYPE_RADIO_MAX+1; name_base = radio; break; default: printk(KERN_ERR %s called with unknown type: %dn, _func_, type); return -1; /* 计算出次设备号 */ mutex_lock(&videodev_lock); if (nr = 0 & nr end-base) /* use the one the driver asked for */ i = base+nr; if (NULL != video_devicei) mutex_unlock(&videodev_lock); return -ENFILE; else /* use first free */ for(i=base;iminor=i; mutex_unlock(&videodev_lock); mutex_init(&vfd-lock); /* sysfs class */ memset(&vfd-class_dev, 0x00, sizeof(vfd-class_dev); if (vfd-dev) vfd-class_dev.parent = vfd-dev; vfd-class_dev.class = &video_class; vfd-class_dev.devt = MKDEV(VIDEO_MAJOR, vfd-minor); sprintf(vfd-class_dev.bus_id, %s%d, name_base, i - base);/ 最后在 /dev 目录下的名称 ret = device_register(&vfd-class_dev);/ 结合 udev 或 mdev 可以实现自动在 /dev 下创建设备节点 从上面的注册函数中可以看出 V4L2 驱动的注册事实上只是完成了设备节点的创建,如: /dev/video0 。和 video_device 结构指针的保存。 ( 3 )视频驱动的打开过程 当用户空间调用 open 打开对应的视频文件时,如: int fd = open(/dev/video0, O_RDWR ); 对应 /dev/video0 的文件操作结构是 /drivers/media/videodev.c 中定义的 video_fops 。 static const struct file_operations video_fops= .owner = THIS_MODULE, .llseek = no_llseek, .open = video_open, ; 奇怪吧,这里只实现了 open 操作。那么后面的其它操作呢?还是先看看 video_open 吧。 static int video_open(struct inode *inode, struct file *file) unsigned int minor = iminor(inode); int err = 0; struct video_device *vfl; const struct file_operations *old_fops; if(minor=VIDEO_NUM_DEVICES) return -ENODEV; mutex_lock(&videodev_lock); vfl=video_deviceminor; if(vfl=NULL) mutex_unlock(&videodev_lock); request_module(char-major-%d-%d, VIDEO_MAJOR, minor); mutex_lock(&videodev_lock); vfl=video_deviceminor; / 根据次设备号取出 video_device 结构 if (vfl=NULL) mutex_unlock(&videodev_lock); return -ENODEV; old_fops = file-f_op; file-f_op = fops_get(vfl-fops);/ 替换此打开文件的 file_operation 结构。后面的其它针对此文件的操作都由新的结构来负责了。也就是由每个具体的 video_device 的 fops 负责。 if(file-f_op-open) err = file-f_op-open(inode,file); if (err) fops_put(file-f_op); file-f_op = fops_get(old_fops); S3C2440的camera接口特性S3C2440是应用十分广泛且适用于嵌入式系统的一款嵌入式处理器。winCE 506O是微软公司开发的一款专用于嵌入式系统的实时操作系统。其模块化设计使开发人员可以根据需求定制设备。目前,国内大部分OEM商都提供了对S3C2440的camera接口在WinCE5O60下的驱动支持。遗憾的是,目前国内OEM商提供的驱动仅限于对几款微型摄像头(如ov9650等)的驱动支持。当用户采用CCD摄像头作为图像采集的前端设备时,原来的驱动已经不能使用了,而CCD摄像头因其优越的性能,在监控领域扮演着主力军角色。本文从分析S3C2440的camera接口特性出发,详细介绍当摄像设备为CCD摄像头时,在WinCE 5O60操作系统环境下开发camera驱动的形式、方法和主要的驱动代码。1 camera接口特性S3C2440处理器有一个专用的camera接口(CAMIF),该接口支持ITU-R BT601656 YCbCr 8位数据格式视频数据输入,最大输入视频图像大小为4 09* 096像素。视频输入后分两个通道逐帧保存图像数据,一个为预览通道(即P通道),另一个为编解码通道(即C通道)。两个通道均通过DMA方式将一帧图像保存到系统内存SDRAM中,在系统内存*开辟了4组帧图像缓冲,从而保证了用户应用程序在读取帧图像数据时不影响另一帧图像数据写入。其特性如下:支持ITU-R BT601656 YCbCr 8位数据格式视频数据输入,并可调整Y、Cb、Cr三个信号的顺序,以适应不同的视频信号源;具有DZI功能,相当于数码变焦;C通道输出图像最大为4 09* 096像素;P通道输出图像最大为640480像素;P通道输出图像格式可配置为RGBl6或GRB24;C通道输出图像格式可配置为YCbCr 4:2:2或YCbCr 4:2:0:输出图像可X方向镜像翻转、Y方向镜像翻转,或180旋转;DMA数据传输,4组帧图像缓冲,2个对应的中断处理,保证视频实时采集;2个通道不同图像数据格式输出,便于用户程序开发。CAMIF对外接口信号定义如下:CAMPCLK输入的视频像素同步时钟。CAMVSYNC输入的视频帧同步时钟。CAMHREF输入的视频行同步时钟。CAMDATA7:0 输入的视频8位数据。CAMCLKOUT输出的时钟,用于外接的没有独立时钟的camera芯片的主时钟。当外接的camera芯片有独立的时钟时,该信号可不用。CAMRESET输出的软件复位信号,可对外接的camera芯片进行复位。信号的时序图如图1所示。使用CAMIF时,必须对CAMIF相关寄存器进行正确配置,下面介绍主要寄存器的配置原理。CAMRCFMT 选择输入视频信号源格式寄存器选择输入视频信号源为ITU-R BT601 YCbCr 8位数据格式,或ITU-R BT656 YCbCr 8位数据格式。选择输入视频信号源水平像素大小和垂直像素大小,一定要和外接的camera设备分辨率一致。选择输入视频信号Ycbcr信号顺序,一定要和外接camera信号的实际顺序一致。CIWDOFST 从输入信号中截取中心部分的图像寄存器原理是:从输入信号中截取中心部分的图像输出到大小不变的输出图像缓冲中,从而实现对图像的放大或缩小。配置该寄存器允许缩放或不允许缩放。X方向图像放大或缩小控制,原理是截切掉左部和右部的图像像素数。Y方向图像放大或缩小控制,原理是截切掉上部和下部的图像像素数。CIGCTRL 全局控制寄存器通过该寄存器对外接的camera进行复位,即控制CAMRESET信号的电平高低。CICOTRGFMT C通道输出图像格式及大小配置寄存器可将C通道输出图像格式配置为YCbCr 4:2:2或YCbCr 4:2:0格式。可设置C通道输出图像X方向像素数。可设置C通道输出图像Y方向像素数。可设置C通道输出图像X方向镜像。可设置C通道输出图像Y方向镜像。可设置C通道输出图像180旋转。CIPRTRGFMT P通道输出图像大小配置寄存器可设置P通道输出图像X方向像素数。可设置P通道输出图像Y方向像素数。可设置P通道输出图像X方向镜像。可设置P通道输出图像Y方向镜像。可设置P通道输出图像180旋转。CICOSTATUS和CIPRSTATUS 状态寄存器CICOSTATUS反映C通道数据的写入状态,即4组缓冲的哪一组;CIPRSTATUS反映P通道数据的写入状态,即4组缓冲的哪一组。用户程序采集图像数据时,应根据状态寄存器当前状态,决定从哪一组读出数据。此外,CICOYSAlCICOYSA4分别为C通道第14帧Y信号数据缓冲起始地址寄存器;CICOCBSAlCICOCBSA4分别为C通道第14帧Cb信号数据缓冲起始地址寄存器;CICOCRSAlCICOCRSA4分别为C通道第14帧Cr信号数据缓冲起始地址寄存器;CIPRCLRSAlCIPRCLRSA4分别为P通道第14帧RGB信号数据缓冲起始地址寄存器。2 WinCE下的驱动开发目前,我国市场上的CCD摄像头只有模拟视频输出接口,显然它不能和S3C2440的camera接口直接连接,硬件上需要增加一块解码芯片。解码芯片把CCD的模拟信号解码为BT601656 YUV4:2:2格式信号,这个信号和CAMIF信号是匹配的,因此解码芯片输出就可以直接连接到S3C2440的camera接口。典型的解码芯片为SAA7113,接口电路如图2所示。如果想简化硬件电路和驱动代码,也可以根据需求向生产商定制CCD摄像头,要求生产商生产的CCD摄像头直接按照ITU-R BT601656格式输出视频信号。具有这种接口的CCD摄像头就可以直接和S3C2440的camera接口连接,接口电路如图3所示。两种情况的驱动代码开发过程基本上是相同的。区别是:前者需要S3C2440通过I2C总线对解码芯片SAA7113的相关寄存器进行配置,而后者则不需要。下面以前者为例介绍驱动的开发方法。21 配置解码芯片SAA7113SAA7113是NXP公司推出的视频解码系列芯片,在很多视频产品(如电视卡、MPEG2、MPEG4)中都有应用。SAA7113的主要作用是把输入模拟视频信号解码成标准的BT656 YUV4:2:2数字信号,相当于一种AD器件。它兼容全球各种视频标准,在我国应用时必须根据我国视频标准来配置内部寄存器。对SAA7113配置需要通过I2C总线进行,分配S3C2440的GPIO的E15模拟I2C的SDA线,E14模拟I2C的SCL线。OEM商提供的原驱动是针对手机摄像头ov9650开发的,二者的配置原理和过程是相同的,但配置内容不同,输出图像的格式也不同。ov9650输出的图像是逐行扫描的,SAA7 113输出的图像则是隔行扫描的。由图1可知,CAMIF是逐帧输入的,所以必须把SAA3117的场同步信号VS作为CAMIF的帧同步信号CAMSYNC,输出图像是逐场保存的。配置内容为:复位SAA3117。模拟通道选择。配置亮度、色度、对比度、自动增益控制量。将RTSl引脚配置为场同步信号VS,将RTSO信号配置为行同步信号HREF,信号极性应分别与图1中CAMVSYNC和CAMHREF信号极性一致。配置图像宽度为720像素。配置帧图像高度为576像素,一帧图像分奇偶两场分时输出,每场图像高度为288像素。配置数据格式为BT656 YCbCr 4:2:2 8位格式输出。注意,数据口的信号顺序为CB0 Y0 CR0 Y1 CBlY2CR359 Y719。时钟采用24576 MHz的独立时钟,此时LLC的频率为27 MHz,场频为50Hz,帧频为25 Hz。22 为CAMlF分配DMA内存空间因为S3C2440从camera接口采集到的视频数据是以DMA机制写到内存的,所以必须为C通道和P通道分别分配逻辑内存(即DMA缓冲区)。Win CE有两种分配DMA缓冲区的方法:使用CEDDK函数和使用winCE内核函数。建议使用CEDDK函数:注意:C通道和P通道应分别分配。分配成功后,应将4组YCbCr信号的起始地址与分配给C通道的DMA缓冲区地址关联起来,将4组RGB信号的起始地址与分配给P通道的DMA缓冲区地址关联起来。格式不同时,关联的空间大小是不同的。如果C通道格式为YCbCr4:2:2,图像宽度为CoDstWidtlh,图像高度为CoDstHeight,分配的DMA地址为CoFrameBuffer,则二者的关联关系为:这样分配的目的是,保证每一组YCbCr信号的地址空间是连续的,便于用户程序开发。如果P通道格式为RGBl6,图像宽度为PrDstWidth,图像高度为PrDstHeight,分配的DMA地址为PrFrame. Buffer,则二者的关联关系为:如果P通道格式为RGB24,图像宽度为PrDstWidth,图像高度为PrDstHeight,分配的DMA地址为PrFrame. Buffer,则二者的关联关系为:23 配置CAMIF相关寄存器把输入视频信号宽度配置为720像素,高度配置为288像素;把输入视频信号格式配置为BT656 YCbcr 4:2:2格式;把输入视频信号顺序配置为CbYCr;根据用户的LCD显示终端的分辨率配置P通道的图像宽度、高度像素和格式;根据用户对图像的处理需求来配置C通道的图像宽度、高度像素和格式;配置C通道的缩放系数;配置P通道的缩放系数;把C通道的DMA地址配置给4组起始地址寄存器;把P通道的DMA地址配置给4组起始地址寄存器。24 创建camera流式驱动接口函数WinCE下的硬件驱动程序大多采用流式驱动来开发,因为它有一个一致的接口函数供用户调用。此处,把接口函数命名为:CAM_Close()、CAM_Deinit()、CAM_Init()、CAM IOControl()、CAM()pen()、CAM PowerDown()、CAM_Power

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论