; 0, TIME serves as a timeout value. The read will be satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1 s). If TIME is exceeded, no character will be returned.
If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The read will be satisfied if MIN characters are received, or the time between two characters exceeds TIME. The timer is restarted every time a character is received and only becomes active after the first character has been received.
If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of characters currently available, or the number of characters requested will be returned. According to Antonino (see contributions), you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result.
By modifying newtio.c_cc[VTIME] and newtio.c_cc[VMIN] all modes described above can be tested.
在非标准输入模式中,输入的数据并不组合成行,也不会进行 erase, kill, delete 等输入处理。我们只是用两个参数来控制这种模式的输入行为: c_cc[VTIME] 设定字符输入间隔时间的计时器,而 c_cc[VMIN] 设置满足读取函数的最少字节数。
MIN > 0, TIME = 0 : 读取函数在读到了 MIN 值的字符数后返回。
MIN = 0, TIME > 0 : TIME 决定了超时值,读取函数在读到一个字节的字符,或者等待读取时间超过 TIME (t = TIME * 0.1s)以后返回,也就是说,即使没有从串口中读到数据,读取函数也会在 TIME 时间后返回。
MIN > 0, TIME > 0 : 读取函数会在收到了 MIN 字节的数据后,或者超过 TIME 时间没收到数据后返回。此计时器会在每次收到字符的时候重新计时,也只会在收到第一个字节后才启动。
MIN = 0, TIME = 0 : 读取函数会立即返回。实际读取到的字符数,或者要读到的字符数,会作为返回值返回。根据 Antonino(参考 conditions), 可以使用 fcntl(fd, F_SETFL, FNDELAY), 在读取前获得同样的结果。
改变了 nettio.c_cc[VTIME] 和 newtio.c_cc[VMIN], 就可以测试以上的设置了。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #define BAUDRATE B38400 #define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#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); /* save current port settings */ bzero(&newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ // 设置输入模式为非标准输入 newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ // 不是用字符间隔计时器 newtio.c_cc[VMIN] = 5; /* blocking read until 5 chars received */ //收到5个字符数以后,read 函数才返回 tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); while (STOP==FALSE) { /* loop for input */ res = read(fd,buf,255); /* returns after 5 chars have been input */ buf[res]=0; /* so we can printf... */ printf(":%s:%d\n", buf, res); if (buf[0]==''''z'''') STOP=TRUE; } tcsetattr(fd,TCSANOW,&oldtio); }
3.3. Asynchronous Input 异步输入模式
#include <termios.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/signal.h> #include <sys/types.h> #define BAUDRATE B38400 #define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX compliant source */ #define FALSE 0 #define TRUE 1
volatile int STOP=FALSE; void signal_handler_IO (int status); /* definition of signal handler */ // 定义信号处理程序 int wait_flag=TRUE; /* TRUE while no signal received */ // TRUE 代表没有受到信号,正在等待中 main() { int fd,c, res; struct termios oldtio,newtio; struct sigaction saio; /* definition of signal action */ // 定义信号处理的结构 char buf[255]; /* open the device to be non-blocking (read will return immediatly) */ // 是用非阻塞模式打开设备 read 函数立刻返回,不会阻塞 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd <0) {perror(MODEMDEVICE); exit(-1); } /* install the signal handler before making the device asynchronous */ // 在进行设备异步传输前,安装信号处理程序 saio.sa_handler = signal_handler_IO; saio.sa_mask = 0; saio.sa_flags = 0; saio.sa_restorer = NULL; sigaction(SIGIO,&saio,NULL);
/* allow the process to receive SIGIO */ // 允许进程接收 SIGIO 信号 fcntl(fd, F_SETOWN, getpid()); /* Make the file descriptor asynchronous (the manual page says only O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ // 设置串口的文件描述符为异步,man上说,只有 O_APPEND 和 O_NONBLOCK 才能使用F_SETFL fcntl(fd, F_SETFL, FAS 上一页 [1] [2] [3] 下一页 |