三菱plc与电脑连接时,提示无法与plc通信,怎么回事啊?请高手指点以下1、没有选择正确的通讯口,或着所选的通讯口被其他程序占用。2、通讯线有问题,三菱plc所用的通讯口是422的方式
cmos摄像头可以在linux中用v4l2编程吗?
linux下怎么样进行摄像头编程
在linux下所有设备都是文件。所以对摄像头的操作其实就是对文件的操作。USB摄像头的设备文件就是在/dev目录下的video0(假如只有一个摄像头)。在linux下操作摄像头就是使用v4l2对摄像头进行的操作,操作步骤如下
打开设备文件。
int fd=open(”/dev/video0″,O_RDWR);
2. 取得设备的capability,看看设备具有什么功能,比如是否具有输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
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:
//……
}
3. 选择输入,一个设备可以有多个输入。VIDIOC_S_INPUT,struct v4l2_input(可不要)
4. 设置的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
struct v4l2_format fmt;
memset ( fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, fmt) < 0)
{
printf("set format failed\n");
//return 0;
}
5. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers
struct v4l2_requestbuffers req;
memset(req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS,req) == -1)
{
perror("VIDIOC_REQBUFS error \n");
//return -1;
}
6.申请物理内存
将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer
VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf("sizeof(VideoBuffer) is %d\n",sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset( buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, buf) < 0)
{
printf("VIDIOC_QUERYBUF error\n");
//return -1;
}
printf("buf len is %d\n",sizeof(buf));
//内存映射
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf("buf2 len is %d\n",sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED)
{
perror("buffers error\n");
//return -1;
}
if (ioctl (fd, VIDIOC_QBUF, buf) < 0)
{
printf("VIDIOC_QBUF error\n");
//return -1;
}
}
7. 开始的采集。
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, type) < 0)
{
printf("VIDIOC_STREAMON error\n");
// return -1;
}
8. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF, 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, buf) < 0)
{
perror("VIDIOC_DQBUF failed.\n");
//return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
unsigned char *ptcur = buffers[numBufs].start;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
int i1;
for(i1=0; i1
{
if((buffers[numBufs].start[i1] == 0xFF) (buffers[numBufs].start[i1+1] == 0xC4))
{
DEBUG("huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n",buf.bytesused,i1);
break;
}
}
if(i1 == buf.bytesused)printf("huffman table don't exist! \n");
int i;
for(i=0; i
{
if((buffers[numBufs].start[i] == 0xFF) (buffers[numBufs].start[i+1] == 0xD8)) break;
ptcur++;
}
DEBUG("i=%d,FF=%02x,D8=%02x\n",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
int imagesize =buf.bytesused - i;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
DEBUG ("imagesize = %d \n",imagesize);
9. 停止的采集。VIDIOC_STREAMOFF
10. 关闭设备。close(fd);
怎样在嵌入式Linux系统中使用摄像头
我觉得linux下无论是USB也好,网卡也好,你的摄像头也好,入门首先要做得就是驱动,因为这些东西最基本的地方就在于驱动程序的设计,而现在网上有关驱动的源码相当成熟,无论是USB还是摄像头,都有可执行的C代码,(可能因为linux是开源的缘故),接下来我建议你做的就是下载下经典的驱动源码,然后简化之,将不是必须的、附加的模块去掉,这个过程一开始是很痛苦的,但是它最大的好处是通过你的删减过程你会完全了解该驱动的构架,最最基本的构架,你会明白摄像头驱动所需要的所有模块,这样底层的东西明了了,上层的模块化设计、接口定义都能做到有的放矢V4L2的编程
v4L2是针对uvc免驱usb设备的编程框架 ,主要用于采集usb摄像头等,编程模式如下: 打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
extern int ioctl (int __fd, unsigned long int __request, …) __THROW;
__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;
__request:具体的命令标志符。
在进行V4L2开发中,一般会用到以下的命令标志符:
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。
这些IO调用,有些是必须的,有些是可选择的。 1. 打开设备文件。
int fd=open(”/dev/video0″,O_RDWR);
2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
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:
//……
}
3. 选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input(可不要)
4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
struct v4l2_format fmt;
/*
v4l2_format 结构如下:
struct v4l2_format
{
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 width; // 宽,必须是16 的倍数
__u32 height; // 高,必须是16 的倍数
__u32 pixelformat; // 视频数据存储类型,例如是YUV 4 :2 :2 还是RGB
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};
*/
样例:
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
{
printf(set format failed\n);
//return 0;
}
5. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers
struct v4l2_requestbuffers
{
__u32 count; // 缓存数量,也就是说在缓存队列里保持多少张照片
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
enum v4l2_memory memory; // V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR
__u32 reserved[2];
};
样例:
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS,&req) == -1)
{
perror(VIDIOC_REQBUFS error \n);
//return -1;
}
6.申请物理内存
将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer
VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf(sizeof(VideoBuffer) is %d\n,sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0)
{
printf(VIDIOC_QUERYBUF error\n);
//return -1;
}
printf(buf len is %d\n,sizeof(buf));
//内存映射
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf(buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n,buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf(buf2 len is %d\n,sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED)
{
perror(buffers error\n);
//return -1;
}
if (ioctl (fd, VIDIOC_QBUF, &buf) < 0)
{
printf(VIDIOC_QBUF error\n);
//return -1;
}
}
7. 开始视频的采集。
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
{
printf(VIDIOC_STREAMON error\n);
// return -1;
}
8. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF, 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)
{
perror(VIDIOC_DQBUF failed.\n);
//return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
unsigned char *ptcur = buffers[numBufs].start;
DEBUG(buf.bytesused = %d \n,buf.bytesused);
int i1;
for(i1=0; i1
if((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4))
{
DEBUG(huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n,buf.bytesused,i1);
break;
}
}
if(i1 == buf.bytesused)printf(huffman table don't exist! \n);
int i;
for(i=0; i
if((buffers[numBufs].start[i] == 0x000000FF) && (buffers[numBufs].start[i+1] == 0x000000D8)) break;
ptcur++;
}
DEBUG(i=%d,FF=%02x,D8=%02x\n,i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
int imagesize =buf.bytesused - i;
DEBUG(buf.bytesused = %d \n,buf.bytesused);
DEBUG (imagesize = %d \n,imagesize);
9. 停止视频的采集。VIDIOC_STREAMOFF
10. 关闭视频设备。close(fd);
罗技c920在linux下对V4L2的支持
首先C920不支持Linux系统,然后它的SDK也没有公布,不支持第三方的软件手机termux运行linux系统,浏览器如何使用手机的摄像头?
在Termux中运行Linux系统的时候,可以通过安装相关的工具和软件来使用手机摄像头。以下是具体的步骤: 首先,需要确保您的Termux已经安装了Linux系统。您可以使用以下命令检查您的Termux是否已经安装了Linux系统: $ proot-distro list 如果输出中包含"debian"或"ubuntu"等Linux系统,则表示您的Termux已经安装了Linux系统。如果没有安装,请使用以下命令安装: $ pkg install proot-distro $ proot-distro install debian 安装v4l2loopback工具。v4l2loopback是一相关文章
- 详细阅读
- 详细阅读
- 详细阅读
- 详细阅读
-
数控加工与编程试题,用g20编程详细阅读
数控编程G20是什么意思G20表示英制输入,G21表示米制输入。机床出厂前一般设定为G21状态,机床的各项参数均以米制单位设定,所以数控车床一般适用于米制尺寸工件加工,如果一个程序
-
这到底是什么意思啊(linux SDL图形详细阅读
什么是linux?他的作用又是什么?Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。严格来讲,Linux这个
-
三菱3U机用步进SFC块编程红绿灯详细阅读
三菱FX系列PLC怎么编写SFC程序块,自动,急停,手动,如何启动与停止这些块。FX系列里有个方便指令叫 IST 可以编写手动,回原点,单步运行,单周期运行,全自动运行,回原点启动,自动运
-
linux服务器上d:\\\upload是什详细阅读
System.IO.DirectoryNotFoundException: 未能找到路径这个问题我前天也遇到了,也是一直报这个异常,搞了很久终于知道了是什么原因,未能找到路径“D:\服务器部署工具\OAPro\oaPr
-
初中毕业学习编程可以吗?详细阅读
初中毕业学习编程可以吗?首先,初中毕业能学会编程,但是,一般达不到太高的造诣。 编程是知识密集型的行业,需要很强的学习能力。初中就毕业了,肯定学习不好。大家的智商都差不多,成
-
在linux 中怎么输入|详细阅读
linux系统中如何打出竖线左手按住键盘上的 SHIFT 键的同时,右手再按靠右边的“|\”组合键,即可打出竖线。linux命令中一竖怎么输入回车键下面那个键 | \ 按住shift按那个键就