用户管理  |   用户注册                                                                                    首 页软件下载教程中心办公指南flash动画文档下载办公公文

www.4oa.com - 中科软件园

投递文章 用户管理 投稿指南 资讯通告 :
站内搜索: 您的位置中科软件园 > 教程中心 > 操作系统 > Linux > 中文HOWTOs > 教程内容

Linux Serial Programming HOWTO (2)

2005-5-25 15:06:17  来源:本站整理  作者:不详 【 投递文章
内容提要:藉由修改newtio.c_cc[VTIME]及newtio.c_cc[VMIN]上述的模式就可以测试了.以下内容为程序代码#include#include#include#include#includ...
藉由修改 newtio.c_cc[VTIME] 及 newtio.c_cc[VMIN] 上述的模式就可以测试了.

以下内容为程序代码 以下内容为程序代码

#include
#include
#include
#include
#include

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX 系统相容 */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
int fd,c, res;
struct termios oldtio,newtio;
char buf[255];

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); exit(-1); }

tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */

bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;

/* 设定输入模式 (非标准型, 不回应,...) */
newtio.c_lflag = 0;

newtio.c_cc[VTIME] = 0; /* 不使用分割字元组计时器 */
newtio.c_cc[VMIN] = 5; /* 在读取到 5 个字元前先停止 */

tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);


while (STOP==FALSE) { /* 输入回圈 */
res = read(fd,buf,255); /* 在输入 5 个字元後即返回 */
buf[res]=0; /* 所以我们能用 printf... */
printf(":%s:%d\n", buf, res);
if (buf[0]=='z') STOP=TRUE;
}
tcsetattr(fd,TCSANOW,&oldtio);
}


3.3 非同步式输入
以下内容为程序代码 以下内容为程序代码

#include
#include
#include
#include
#include
#include

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX 系统相容 */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

void signal_handler_IO (int status); /* 定义讯号处理程序 */
int wait_flag=TRUE; /* 没收到讯号的话就会是 TRUE */

main()
{
int fd,c, res;
struct termios oldtio,newtio;
struct sigaction saio; /* definition of signal action */
char buf[255];

/* 开启装置为 non-blocking (读取功能会马上结束返回) */
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd <0) {perror(MODEMDEVICE); exit(-1); }

/* 在使装置非同步化前, 安装讯号处理程序 */
saio.sa_handler = signal_handler_IO;
saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);

/* 允许行程去接收 SIGIO 讯号*/
fcntl(fd, F_SETOWN, getpid());
/* 使档案ake the file des criptor 非同步 (使用手册上说只有 O_APPEND 及
O_NONBLOCK, 而 F_SETFL 也可以用...) */
fcntl(fd, F_SETFL, FASYNC);

tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定值 */
/* 设定新的序列埠为标准输入程序 */
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);

/* 等待输入讯号的回圈. 很多有用的事我们将在这做 */
while (STOP==FALSE) {
printf(".\n");usleep(100000);
/* 在收到 SIGIO 後, wait_flag = FALSE, 输入讯号存在则可以被读取 */
if (wait_flag==FALSE) {
res = read(fd,buf,255);
buf[res]=0;
printf(":%s:%d\n", buf, res);
if (res==1) STOP=TRUE; /* 如果只输入 CR 则停止回圈 */
wait_flag = TRUE; /* 等待新的输入讯号 */
}
}
/* 回存旧的序列埠设定值 */
tcsetattr(fd,TCSANOW,&oldtio);
}

/***************************************************************************
* 讯号处理程序. 设定 wait_flag 为 FALSE, 以使上述的回圈能接收字元 *
***************************************************************************/

void signal_handler_IO (int status)
{
printf("received SIGIO signal.\n");
wait_flag = FALSE;
}


3.4 等待来自多个讯号来源的输入
这一段很短. 它只能被拿来当成写程式时的提示, 故□例程式也很简短. 但这个□例不只能用在序列埠上, 还可以用在被当成档案来使用的装置上.

select 呼叫及伴随它所引发的巨集共用 fd_set. fd_set 则是一个位元阵列, 而其中每一个位元代表一个有效的档案叙述结构. select 呼叫接受一个有效的档案叙述结构并传回 fd_set 位元阵列, 而该位元阵列中若有某一个位元为 1, 就表示相对映的档案叙述结构的档案发生了输入, 输出或有例外事件. 而这些巨集提供了所有处理 fd_set 的功能. 亦可参考手册 select(2).

以下内容为程序代码 以下内容为程序代码

#include
#include
#include

main()
{
int fd1, fd2; /* 输入源 1 及 2 */
fd_set readfs; /* 档案叙述结构设定 */
int maxfd; /* 最大可用的档案叙述结构 */
int loop=1; /* 回圈在 TRUE 时成立 */

/* open_input_source 开启一个装置, 正确的设定好序列埠,
并回传回此档案叙述结构体 */
fd1 = open_input_source("/dev/ttyS1"); /* COM2 */
if (fd1<0) exit(0);
fd2 = open_input_source("/dev/ttyS2"); /* COM3 */
if (fd2<0) exit(0);
maxfd = MAX (fd1, fd2)+1; /* 测试最大位元输入 (fd) */

/* 输入回圈 */
while (loop) {
FD_SET(fd1, &readfs); /* 测试输入源 1 */
FD_SET(fd2, &readfs); /* 测试输入源 2 */
/* block until input becomes available */
select(maxfd, &readfs, NULL, NULL, NULL);
if (FD_ISSET(fd1)) /* 如果输入源 1 有讯号 */
handle_input_from_source1();
if (FD_ISSET(fd2)) /* 如果输入源 2 有讯号 */
handle_input_from_source2();
}

}

这个□例程式在等待输入讯号出现前, 不能确定它会停顿下来. 如果你需要在输入时加入逾时功能, 只需把 select 呼叫换成:

int res;
str

[1] [2]  下一页

(评论内容只代表网友观点,与本站立场无关!)[ 全部评论 ]

网友评论:

    用户名:

    评   分:100分 85分 70分 55分 40分 25分 10分 0分

    内 容:

                 (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码

关于本站 - 网站帮助 - 广告合作 - 下载声明 - 友情连接 - 网站地图 -有事点这里