请问一下linux的串口中断是怎么实现的
driver/char/serial.c
在 static int startup(struct async_struct * info) 函数中设置
一般为以下三个函数中的一个
rs_interrupt_multi
rs_interrupt
rs_interrupt_single
======================================================
看了很多关于串口编程的例子,大都是先初始化,设置波特率等,然后就用一个while(1)一直读串口,想请高手指点一下,能否用中断机制,而不要一直查询呢,谢谢
----------------------
在while中使用select,这样应该可以的。
-----------------------
需要用到:1、select 2、singal
----------------------
可以这样
1)新建立一个线程使用select来监听串口,发现数据发送出一个信号
2)打开的时候使用O_ASYNC标志,处理SIGIO信号
SIGIO不是异步IO,只是IO的信号机制,异步IO是AIO的方式
------------------------
============================================================
各位大侠,小弟先急需写一个类似DOS下面的串口中断接收发送数据的程序,由于第一次用Linux,不清楚怎么用,看了看,好像应该是对设备的信号量的操作,大家给点代码看看,谢谢
具体的是这样,主程序是一个死循环(在计算数据),这个时候,需要响应串口传过来的数据进行计算,需中断响应,这个程序怎么写?我用了termios这个结构,很奇怪的是,可以接收(用信号,听说这个类似DOS的INT),但是不能够发送,不知道哪里出错了,相串口发送数据是(write(fd,buff,100))这个函数吗?
有其他的函数吗?我在DOS下面用的outportb这个,直接对地址发送(outportb(0x3f8,buff,1))Linux下面的outb这个函数是否一样,给小弟一个解答!!写谢谢!!
---------------------------
给个简单例子:
void sService()
{
struct timeval WaitTime;
int ret,MaxFd;
int nread,nwrite,i,j;
fd_set readfs;
WaitTime.tv_sec = 0;
WaitTime.tv_usec = 20000;
FD_ZERO(&readfs);
FD_SET(fd[0],&readfs);
FD_SET(fd[1],&readfs);
FD_SET(fd[2],&readfs);
FD_SET(fd[3],&readfs);
FD_SET(fd[4],&readfs);
FD_SET(fd[5],&readfs);
FD_SET(fd[6],&readfs);
FD_SET(fd[7],&readfs);
MaxFd = MAX(8,fd)+1;
ret = select(MaxFd, &readfs, NULL, NULL, &WaitTime);
if (ret>0)
{
for (i=0;i<8;i++)
{
if (FD_ISSET(fd, &readfs))
{
//接收串口数据
}
}
}
}
int main(int argc,char *argv[])
{
signal(SIGIO,sService);
while(1)
{
//业务处理
}
}
-----------------------------------------
你不能在你的程序中直接调用端口读写函数,必须利用驱动程序去读写。对串口和对文件操作差不多。就是多了设置串口这一步。
open(...)
tcsetattr(...)
read(...)/write(...)
close(...)
So EZ!
------------------------------------
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAS_GETOPT_H
#include <getopt.h>
#endif
extern char* optarg;
#include <liberror/liberror.h>
#include <libtty/libtty.h>
#define USAGE_MSG \
"modemtalk (" ## VERSION ## ")\n"\
"usage:\n" \
" modemtalk [-h] [-m dev]\n" \
"\n" \
"where options include:\n" \
" -h print out this message\n" \
" -m dev use modem device dev\n" \
" -v displays version information\n"\
"\n"
#define VERSION_MSG \
"modemtalk version " ## VERSION ## "\n"
static char* opt_string = "hm:v";
static void usage()
{
fprintf( stdout, USAGE_MSG );
}
static void version()
{
fprintf( stdout, VERSION_MSG );
}
void main( int argc, char* argv[] )
{
int fdesc;
int bytes;
int i;
int dest;
int nfsd;
int c;
fd_set io;
char buf[512];
char* device;
/* get device name from environment */
device = getenv( "MODEM" );
/* parse command line arguments */
while( 1 )
{
c = getopt( argc, argv, opt_string );
if( c == -1 )
break;
switch( c )
{
case 'h' :
usage();
exit( 0 );
case 'm' :
device = strdup( optarg );
break;
case 'v' :
version();
exit( 0 );
default:
exit( 1 );
break;
}
}
/* open terminal (modem) device */
fdesc = open( device, O_RDWR );
if( fdesc == -1 )
{
FAIL( "open" );
exit( 1 );
}
ttySetRaw( STDIN_FILENO );
/*
* enter loop. Data reseived from stdin is copied to fdesc.
* data read from fdesc is written to stdout
*/
while( 1 )
{
FD_ZERO( &io );
FD_SET( fdesc, &io );
FD_SET( STDIN_FILENO, &io );
nfsd = select( FD_SETSIZE, &io, NULL, NULL, NULL );
if( nfsd < 0 )
{
FAIL( "select" );
exit( 1 );
}
if( nfsd > 0 )
for( i = 0; i < FD_SETSIZE; i++ )
if( FD_ISSET( i, &io ) )
{
if( i == STDIN_FILENO )
dest = fdesc;
else
dest = STDOUT_FILENO; /* stdout */
/* read from device */
bytes = read( i, buf, sizeof( buf ) );
if( bytes < 0 )
{
FAIL( "read" );
exit( 1 );
}
/* eof */
if( bytes == 0 )
exit( 0 );
bytes = write( dest, buf, bytes );
if( bytes < 0 )
{
FAIL( "write" );
exit( 1 );
}
if( bytes == 0 )
exit( 0 ); /* eof */
}
}
}
-------------------------------------------
http://www-900.ibm.com/developerWorks/cn/linux/l-serials/index.shtml
Linux下串口编程入门
---------------------------------------------
你在Linux下是不能使用中断来写程序的,除非你写Linux驱动来实现。这和DOS不一样,因为Linux是运行在保护模式下的。
-------------------------------------
你的UART芯片是什么?你的卡是ISA的还是PCI的?如果是现成的卡,那你利用Linux自带的drivers\char\serial.c修改一下就可以了,这个文件支持大多数目前流行的UART。
------------------------------------
好好看看Linux的串口书籍。
-----------------------------------
===============================================================
我正在编一个串口程序,是用TTY吧?但我找的所有LINUX串口程序都是这样做的
while(1)
{
while((nread = read(fd,buff,512))>0)
{
printf("\n%s",buff);
}
}
怎么样才能实现在LINUX下的串口中断接收呀,是不是TTY不支持呀
-------------------------------------
如果你想在应用程序中实现中断接收的话,可以模仿一个,就是用多线程加信号的方式,开辟一个新的线程轮询串口,收到数据后就向主线程发信号,对于主线程来说,相当于是中断接收了
-------------------------------------
====================================================================
需要在linux下用中断方式来写一个串口的程序,现在没有思路,网上有人说用select,signal,tasklet函数的,但是我没看懂,希望有做过的给一下例程,多谢!
----------------------------
Linux下用中断方式 ?
内核态才有中断, 用户态,只有软中断 即 信号。
你想要什么样子的?
----------------------------
就是能够当串口数据来临时自动通知串口读取数据,类似于中断,以前在windows下面做串口时用的是单独开辟一个线程来监测信号量,不知道在Linux下面怎么实现
----------------------------
linux 下跟windows 下差不多, 最好也是开一个线程来处理。
-----------------------------
http://www.ibm.com/developerworks/cn/linux/l-serials/index.html
建议你看看这篇文章。
-----------------------------
最好是单处开1个进程,线程会阻塞其他同进程的线程!
==================================================================
我是新来的linux菜鸟,以后还请大家多多帮助.在这里谢谢了.
我现在要在linux下进行串口通信,程序用C编写,然后移植到ARM中,现在我很困惑关于串口的读写问题,我看了大多数程序只能在while循环里反复的读写串口,这样太浪费资源,我没有时间处理接收过来的数据了,还有就是使用select() 定时查询也很麻烦,关键是我不知道外部数据什么时候进来,请问有没有其他中断的方法,好比C51中有数据进入RI自动置位,进入串口中断程序.
可能问题比较幼稚,还请各位大侠帮帮忙,我在网上查了好长时间也没有查到,谁有这方面例程请给我一个,谢谢!.
-----------------------------
select调用,属于事件、超时触发!意思是:在设定的时间内,如果串口有数据,则不用等到超时,系统就会唤醒程序处理;如果到了设定的时间还没有数据,系统也会唤醒程序处理超时情况!select()的响应时间粒度在2.4上是10ms!在2.6上,比这个时间更短(应为可抢占的因素)
=================================================================
我在linux系统下写的串口程序,需要实时的读取串口来的数据,但串口来的数据又是不定时的,想用中断的方式响应,看了一些资料,总觉的还所有些不妥。
首先,select函数,他需要一直在while中检测读文件描述符是否有变化,但串口来了数据会改变文件描述符吗?(即使我的串口一直处在open状态中)另外,即使能检测到文件描述符有了变化,那程序也都一直在while中,CPU将不能再做其他的事情。
其次,signal函数,串口来了数据,系统会自动广播SIGIO信号吗?即使能捕捉的这个信号,程序进入中断服务子程序中执行,那下一个串口数据又如何响应,难道在中断子程序的结尾再调用 signal函数吗?那CPU又将陷入这个等待串口数据的程序中,而不能做其他的事情了,而且SIGIO信号怎么能保证就是串口来的呢?
最后,tasklet,这个中断机制如何实现,他应该是在串口硬中断服务程序中定义中断的下班部分的入口,但这个硬中断服务程序又在什么地方?需要修改内核吗?
上只是我个人的理解,如有不正确的,请过来人指教。我现在希望串口数据能像以前用单片机一样,真正实现中断响应,只有当串口来数据时,CPU或者内核才会去执行串口读相关动作,串口没有数据时,CPU或者内核是完全不会理会串口的,不知哪位高人可以指点一下,如何来实现?
-------------------------------------
可以起一个线程,用select函数,其实这个函数很好用,你看看书,unix系统编程、unix网络编程上都有详细介绍。
-------------------------------------
首先,select函数,他需要一直在while中检测读文件描述符是否有变化,但串口来了数据会改变文件描述符吗?(即使我的串口一直处在open状态中)另外,即使能检测到文件描述符有了变化,那程序也都一直在while中,CPU将不能再做其他的事情。
答:select 的函数不需要每个cpu的时间片都去查询文件描述符是否发生过变化,
while(1)
{
sleep(200);
select();//这样就不会造成cpu的一直占用了。
}
http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html
---------------------------------------
linux 下的标准串口,在核心的驱动程序中是通过中断方式处理的。
你如果做的是应用层的程序,那么可以采用 select 方式监测“读文件描述符”。
select 也并非你说的那样一直 while 等待方式,它是在中断中接收到对端发来
的数据后唤醒并通知应用程序:串口接收到数据 ...
如果你要像单片机方式,那么就需要实现一个自己的串口驱动运行在核心 ...
--------------------------------------
文章评论(0条评论)
登录后参与讨论