我是linux编程的新手。我按照Web上的示例来读/写控制台,例如“/ dev / ttyS0”。每次运行代码时,它都会退出而不会提示用户写入输入。它也会扭曲终端提示符(换行符),我无法看到我正在输入的内容......这是我正在使用的代码:
int main(int argc, char** argv)
{
struct termios tio;
struct termios stdio;
int tty_fd;
/* fd_set rdset; */
printf("Please start with %s /dev/ttyS0 (for example)\n",argv[0]);
unsigned char mesg='D';
memset(&stdio,0,sizeof(stdio));
stdio.c_iflag=0;
stdio.c_oflag=0;
stdio.c_cflag=0;
stdio.c_lflag=0;
stdio.c_cc[VMIN]=1;
stdio.c_cc[VTIME]=0;
tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking
memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;
tty_fd=open(argv[1], O_RDWR | O_NONBLOCK | O_NOCTTY);
cfsetospeed(&tio,B115200); // 115200 baud
cfsetispeed(&tio,B115200); // 115200 baud
tcsetattr(tty_fd,TCSANOW,&tio);
while (mesg != 'q') {
if (read(tty_fd,&mesg,1)>0) write(STDOUT_FILENO,&mesg,1); // if new data is available on the serial port, print it out
if (read(STDIN_FILENO,&mesg,1)>0) write(tty_fd,&mesg,1); // if new data is available on the console, send it to the serial port
}
close(tty_fd);
return(0);
}
答案 0 :(得分:1)
当您尝试更改tty参数的代码时,您应该使用保存和恢复参数的脚本包装测试程序的调用,以防程序忽略这样做。
这可以这样做:
$ SAVED_TTY=$(stty -g) # save the good settings once
$ ./a.out ; stty $SAVED_TTY # restore than after each run of the program
-g
的{{1}}选项使其将所有tty设置“pickled”输出到字符串中,这可以作为将来stty
调用的参数恢复相同的设置。
(正确编写的tty操作程序在退出时会注意恢复终端设置,即使它们通过接收任何可以处理的致命信号而突然退出。)
至于如何循环回写入tty设备的内容的问题,tty子系统本身没有这方面的一般功能。标准的tty线路规则模块可以将传入的字符回显给输出,这样当用户使用面向行的程序时,他们可以看到自己的输入,但是没有软件环回,因此tty设备假装接收到它有的一些字符刚送过。
然而,某些串行硬件能够进行硬件环回:基本上将UART TX线连接到RX线以进行测试。
Linux tty支持调制解调器控制ioctl,如果硬件支持,它可用于打开和关闭它。这采用stty
和TIOCMGET
ioctls的形式。这些ioctl使用的值是各种掩码的逻辑或,其中一个是TIOCMSET
。
所以,我认为设置硬件环回会是这样的:
TIOCM_LOOP
如果要求设置unsigned int modem_control_bits;
result = ioctl(tty_descriptor, TIOCMGET, &modem_control_bits);
/* check result for error, of course */
modem_control_bits |= TIOCM_LOOP; /* request loopback from serial port */
result = ioctl(tty_descriptor, TIOCMSET, &modem_control_bits);
/* check result for error */
,但是硬件不支持,则每个串行驱动程序是否会报告错误尚不清楚。 (我不认为只是因为结果为零,它必然有效)。
还有其他TIOCM_LOOP
位,因此您可以执行标准操作,例如打开和关闭DTR,或检测指示灯是否亮起等等。