Linux Serial Programming HOWTO (2)
时间:2007-02-17 来源:PHP爱好者
藉由修改 newtio.c_cc[VTIME] 及 newtio.c_cc[VMIN] 上述的模式就可以测试了.
CODE:
[复制到剪切板]
<br>#include <br>#include <br>#include <br>#include <br>#include <br><br>#define BAUDRATE B38400 <br>#define MODEMDEVICE "/dev/ttyS1" <br>#define _POSIX_SOURCE 1 /* POSIX 系统相容 */ <br>#define FALSE 0 <br>#define TRUE 1 <br><br>volatile int STOP=FALSE; <br><br>main() <br>{ <br>int fd,c, res; <br>struct termios oldtio,newtio; <br>char buf[255]; <br><br>fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); <br>if (fd <0) {perror(MODEMDEVICE); exit(-1); } <br><br>tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定 */ <br><br>bzero(&newtio, sizeof(newtio)); <br>newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; <br>newtio.c_iflag = IGNPAR; <br>newtio.c_oflag = 0; <br><br>/* 设定输入模式 (非标准型, 不回应,...) */ <br>newtio.c_lflag = 0; <br><br>newtio.c_cc[VTIME] = 0; /* 不使用分割字元组计时器 */ <br>newtio.c_cc[VMIN] = 5; /* 在读取到 5 个字元前先停止 */ <br><br>tcflush(fd, TCIFLUSH); <br>tcsetattr(fd,TCSANOW,&newtio); <br><br>while (STOP==FALSE) { /* 输入回圈 */ <br>res = read(fd,buf,255); /* 在输入 5 个字元後即返回 */ <br>buf[res]=0; /* 所以我们能用 printf... */ <br>printf(":%s:%dn", buf, res); <br>if (buf[0]=='z') STOP=TRUE; <br>} <br>tcsetattr(fd,TCSANOW,&oldtio); <br>} <br> ;
php爱好者站 http://www.phpfans.net 网页特效|网页模板
3.3 非同步式输入
3.3 非同步式输入
CODE:
[复制到剪切板]
<br>#include <br>#include <br>#include <br>#include <br>#include <br>#include <br><br>#define BAUDRATE B38400 <br>#define MODEMDEVICE "/dev/ttyS1" <br>#define _POSIX_SOURCE 1 /* POSIX 系统相容 */ <br>#define FALSE 0 <br>#define TRUE 1 <br><br>volatile int STOP=FALSE; <br><br>void signal_handler_IO (int status); /* 定义讯号处理程序 */ <br>int wait_flag=TRUE; /* 没收到讯号的话就会是 TRUE */ <br><br>main() <br>{ <br>int fd,c, res; <br>struct termios oldtio,newtio; <br>struct sigaction saio; /* definition of signal action */ <br>char buf[255]; <br><br>/* 开启装置为 non-blocking (读取功能会马上结束返回) */ <br>fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); <br>if (fd <0) {perror(MODEMDEVICE); exit(-1); } <br><br>/* 在使装置非同步化前, 安装讯号处理程序 */ <br>saio.sa_handler = signal_handler_IO; <br>saio.sa_mask = 0; <br>saio.sa_flags = 0; <br>saio.sa_restorer = NULL; <br>sigaction(SIGIO,&saio,NULL); <br><br>/* 允许行程去接收 SIGIO 讯号*/ <br>fcntl(fd, F_SETOWN, getpid()); <br>/* 使档案ake the file descriptor 非同步 (使用手册上说只有 O_APPEND 及 <br>O_NONBLOCK, 而 F_SETFL 也可以用...) */ <br>fcntl(fd, F_SETFL, FASYNC); <br><br>tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定值 */ <br>/* 设定新的序列埠为标准输入程序 */ <br>newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; <br>newtio.c_iflag = IGNPAR | ICRNL; <br>newtio.c_oflag = 0; <br>newtio.c_lflag = ICANON; <br>newtio.c_cc[VMIN]=1; <br>newtio.c_cc[VTIME]=0; <br>tcflush(fd, TCIFLUSH); <br>tcsetattr(fd,TCSANOW,&newtio); <br><br>/* 等待输入讯号的回圈. 很多有用的事我们将在这做 */ <br>while (STOP==FALSE) { <br>printf(".n");usleep(100000); <br>/* 在收到 SIGIO 後, wait_flag = FALSE, 输入讯号存在则可以被读取 */ <br>if (wait_flag==FALSE) { <br>res = read(fd,buf,255); <br>buf[res]=0; <br>printf(":%s:%dn", buf, res); <br>if (res==1) STOP=TRUE; /* 如果只输入 CR 则停止回圈 */ <br>wait_flag = TRUE; /* 等待新的输入讯号 */ <br>} <br>} <br>/* 回存旧的序列埠设定值 */ <br>tcsetattr(fd,TCSANOW,&oldtio); <br>} <br><br>/*************************************************************************** <br>* 讯号处理程序. 设定 wait_flag 为 FALSE, 以使上述的回圈能接收字元 * <br>***************************************************************************/ <br><br>void signal_handler_IO (int status) <br>{ <br>printf("received SIGIO signal.n"); <br>wait_flag = FALSE; <br>} <br> ;
php爱好者站 http://www.phpfans.net 网页制作|网站建设|数据采集.
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();
}
}
php爱好者站 http://www.phpfans.net Linux|Apache|IIS.
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();
}
}
php爱好者站 http://www.phpfans.net Linux|Apache|IIS.
相关阅读 更多 +